X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=asm.pm;h=1b6dc8ad82e0d98ad48dd0583098eb8279979a7b;hb=46a95fd39e0ef114dd837bed285f8ca6acf6bb32;hp=d07004e5cc6cf65e78b1c42c7dfc617826b170bb;hpb=23c26e0422eda4cb868569e6c3cc4f41fe6e2864;p=clump.git diff --git a/asm.pm b/asm.pm index d07004e..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,16 +128,51 @@ 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 } +sub flag_temp { 7 } sub flag_news { 8 + $_[0] } @@ -149,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; @@ -163,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; @@ -172,3 +255,71 @@ sub addC { my ($addrA, $addrB, $addrC, $flag_carry) = @_; 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 { + my ($nX, $nY, $dest) = @_; + my %dest = %$dest; + while ($nX || $nY) { + my $direction; + if ($nX > 0) { + $nX--; + $direction = 2; + } elsif ($nX < 0) { + $nX++; + $direction = 0; + } elsif ($nY > 0) { + $nY--; + $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 + } elsif (exists $dest{address}) { + alu3 alu_select_f, alu_select_f, 0, 0, $dest{address}, flag_news($direction), flag_zero + } elsif (exists $dest{flag}) { + alu3 alu_select_f, alu_select_a, 0, 0, 0, flag_news($direction), $dest{flag} + } else { + die "No destination address nor flag given to [news_generic]\n" + } + } +} + +sub news_mm { + my ($addrIN, $addrOUT, $nX, $nY) = @_; + alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero; + news_generic $nX, $nY, {address => $addrOUT}; +} + +sub news_mf { + my ($addrIN, $flagOUT, $nX, $nY) = @_; + alu3 alu_select_a, alu_select_a, $addrIN, 0, $addrIN, flag_zero, flag_zero; + news_generic $nX, $nY, {flag => $flagOUT}; +} + +sub news_fm { + my ($flagIN, $addrOUT, $nX, $nY) = @_; + alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero; + news_generic $nX, $nY, {address => $addrOUT}; +} + +sub news_ff { + my ($flagIN, $flagOUT, $nX, $nY) = @_; + alu3 alu_select_f, alu_select_a, 0, 0, 0, $flagIN, flag_zero; + news_generic $nX, $nY, {flag => $flagOUT}; +} + +1;