X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=asm.pm;h=1b6dc8ad82e0d98ad48dd0583098eb8279979a7b;hb=refs%2Fheads%2Fcurium;hp=492bfccc1e2764dce4e1a4c0f20a3f615a17e854;hpb=3b542afc856d736dfd2ff0eed081f647de07af4c;p=clump.git diff --git a/asm.pm b/asm.pm index 492bfcc..1b6dc8a 100644 --- a/asm.pm +++ b/asm.pm @@ -7,10 +7,10 @@ use constant +{ OP_LOADA => 1, OP_LOADB => 2, OP_STORE => 3, - OP_READ => 4, + OP_STOREI => 4, OP_LOADI => 5, OP_ROUTE => 6, - OP_RUG => 7, + OP_LED => 7, }; q, @@ -28,19 +28,22 @@ $port->read_const_time(2000); $port->write_settings or die "$!"; ,; -use Fcntl; +#use Fcntl; use Time::HiRes qw/sleep/; -sysopen my $port, '/dev/ttyUSB1', O_SYNC | O_RDWR or die "$!"; +my $port; +#sysopen $port, '/dev/ttyUSB1', O_SYNC | O_RDWR or die "$!"; use parent qw/Exporter/; -our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC/; -our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC/; +our @EXPORT = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/; +our @EXPORT_OK = qw/loada loadb store write_verilog alu_select_a alu_select_b alu_select_f alu_zero flag_zero flag_news alu_xor alu_xnor alu_or alu_of_function aluc_add alus_add aluc_addAF alus_addAF alu2 alu3 add addC loadi storei ledm ledi route chip_select/; use File::Slurp::Tiny 'write_file'; -sub send_ { +=begin comment + +sub send__ { my ($cmd) = @_; my %cmd = %$cmd; @@ -60,6 +63,39 @@ sub send_ { } } +=end + + +=cut + +my $rom_cnt = 0; + +# by default instructions are for all 4 chips to execute +our $CS = 0xF; + +sub send_ { + my ($cmd) = @_; + my %cmd = %$cmd; + my $op_cs = $cmd{op} + ($CS << 4); + + my $binary = pack 'vCC', $cmd{I}, $cmd{mem_addr}, $op_cs; + my $hex = reverse unpack 'h*', $binary; + # say "$rom_cnt: data <= 32'h$hex;"; + say $hex; + $rom_cnt++; +} + +sub chip_select { + my ($new_cs, $sub) = @_; + local $CS = $new_cs; + $sub->(); +} + +sub nop { + send_ + { I => 0, mem_addr => 0, op => OP_NOP } + } + sub loada { my ($addr, $flagr, $bsel, $aluc) = @_; my $I = 0; @@ -67,7 +103,7 @@ sub loada { $I |= $bsel << 4; $I |= $aluc << 5; send_ - { I => $I, mem_addr => $addr, op => OP_LOADA, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADA } } sub loadb { @@ -77,13 +113,13 @@ sub loadb { $I |= $inv << 4; $I |= $alus << 5; send_ - { I => $I, mem_addr => $addr, op => OP_LOADB, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADB } } -sub read_ { - my ($addr) = @_; - send_ { I => 0, mem_addr => $addr, op => OP_READ, CS => 1 } -} +#sub read_ { +# my ($addr) = @_; +# send_ { I => 0, mem_addr => $addr, op => OP_READ, CS => 1 } +#} sub store { my ($addr, $flagw, $edge_, $cube) = @_; @@ -92,13 +128,47 @@ sub store { $I |= $edge_ << 7; $I |= $cube << 8; send_ - { I => $I, mem_addr => $addr, op => OP_STORE, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_STORE } } sub loadi { my ($addr, $I) = @_; send_ - { I => $I, mem_addr => $addr, op => OP_LOADI, CS => 0 } + { I => $I, mem_addr => $addr, op => OP_LOADI } +} + +sub route { + my ($addr, $dest_addr, $led) = @_; + $led //= 0; + my $I = $dest_addr; + $I |= $led << 12; + send_ + { I => $I, mem_addr => $addr, op => OP_ROUTE } +} + +sub storei { + my ($addr, $I) = @_; + send_ + { I => $I, mem_addr => $addr, op => OP_STOREI } +} + +sub led { + my ($addr, $mode, $offset_leds) = @_; + my $I = $offset_leds; + $I |= $mode << 4; + send_ + { I => $I, mem_addr => $addr, op => OP_LED } +} + +sub ledm { + my ($addr, $offset) = @_; + $offset //= 0; + led $addr, 1, $offset; +} + +sub ledi { + my ($leds) = @_; + led 0, 0, $leds; } sub flag_zero { 0 } @@ -150,6 +220,13 @@ sub alus_addAF { alu_of_function { ($a + $_) & 1 } } sub alu_or { alu_of_function { $a | $b | $_ } } +sub alu_and { alu_of_function { $a & $b & $_ } } + +BEGIN { + die "alus_add != alu_xor" unless alus_add == alu_xor; + die "bad alu_select_f" unless alu_select_f == alu_of_function { $_ }; +} + sub alu2 { my ($aluc, $alus, $addrA, $addrB, $flagr, $flagw, $cond, $inv) = @_; loada $addrA, $flagr, 0, $aluc; @@ -164,6 +241,11 @@ sub alu3 { store $addrC, $flagw, 0, 0; } +sub mov { + my ($addrA, $addrC) = @_; + alu3 alu_zero, alu_select_a, $addrA, $addrA, $addrC, flag_zero, flag_zero +} + sub add { my ($addrA, $addrB, $addrC, $flag_carry) = @_; alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, flag_zero, $flag_carry; @@ -174,6 +256,16 @@ sub addC { alu3 aluc_add, alus_add, $addrA, $addrB, $addrC, $flag_carry, $flag_carry; } +sub xor_ { + my ($addrA, $addrB, $addrC) = @_; + alu3 alu_zero, alu_xor, $addrA, $addrB, $addrC, flag_zero, flag_zero; +} + +sub and_ { + my ($addrA, $addrB, $addrC) = @_; + alu3 alu_zero, alu_and, $addrA, $addrB, $addrC, flag_zero, flag_zero; +} + # news_gen face partea de mijloc # news_[mf][mf] face primul alu3, apeleaza news_gen, apoi face ultimul alu3 sub news_generic { @@ -181,16 +273,18 @@ sub news_generic { my %dest = %$dest; while ($nX || $nY) { my $direction; - if ($nX && $nY) { - $nX--; - $nY--; - $direction = 7; - } elsif ($nX) { + if ($nX > 0) { $nX--; + $direction = 2; + } elsif ($nX < 0) { + $nX++; $direction = 0; - } else { + } elsif ($nY > 0) { $nY--; - $direction = 6; + $direction = 1; + } elsif ($nY < 0) { + $nY++; + $direction = 3; } if ($nX || $nY) { # not the last go alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), flag_zero @@ -227,3 +321,5 @@ sub news_ff { alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero; news_generic $nX, $nY, {flag => $flagOUT}; } + +1;