diff --git a/LX9Co-32016.xise b/LX9Co-32016.xise new file mode 100644 index 0000000..bd688bf --- /dev/null +++ b/LX9Co-32016.xise @@ -0,0 +1,476 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/README.md b/README.md deleted file mode 100644 index cb4f0d3..0000000 --- a/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Matchbox CoPro -============== - -A family of designs for the Matchbox Co Pro for the BBC Micro. - -For more details on the designs, see: -http://stardot.org.uk/forums/viewtopic.php?t=8852&f=44 - -For Jason's LX9 Hardware, see: -http://stardot.org.uk/forums/viewtopic.php?t=8932&f=8 - -DIP Switch Settings: -0 0 0 0 - 4MHz 65C102 (512KB external RAM using Jason's paging extensions) -0 0 0 1 - 8MHz Z80 ( 64KB external RAM) -0 0 1 0 - 4MHz 6809 ( 64KB external RAM) -0 0 1 1 - 16Mhz 80x86 (512KB external RAM) -0 1 0 0 - BIST -0 1 0 1 - unused -0 1 1 0 - unused -0 1 1 1 - unused -1 0 0 0 - 32MHz 65C102 (64KB internal RAM, boot message shows speed) -1 0 0 1 - 16MHz 65C102 (64KB internal RAM, boot message shows speed) -1 0 1 0 - 8MHz 65C102 (64KB internal RAM, boot message shows speed) -1 0 1 1 - 4MHz 65C102 (64KB internal RAM, boot message shows speed) -1 1 0 0 - 112 MHz Z80 (64KB internal RAM, now using NextZ80 core) -1 1 0 1 - 56 MHz Z80 (64KB internal RAM, now using NextZ80 core) -1 1 1 0 - 32 MHz Z80 (64KB internal RAM, now using NextZ80 core) -1 1 1 1 - 16 MHz Z80 (64KB internal RAM, now using NextZ80 core) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..0afe596 --- /dev/null +++ b/README.txt @@ -0,0 +1,28 @@ +Matchbox CoPro +============== + +A family of designs for the Matchbox Co Pro for the BBC Micro. + +For more details on the designs, see: +http://stardot.org.uk/forums/viewtopic.php?t=8852&f=44 + +For Jason's LX9 Hardware, see: +http://stardot.org.uk/forums/viewtopic.php?t=8932&f=8 + +DIP Switch Settings: +0 0 0 0 - 4MHz 65C102 ( 64KB internal RAM, AlanD core) +0 0 0 1 - 8MHz 65C102 ( 64KB internal RAM, AlanD core) +0 0 1 0 - 16MHz 65C102 ( 64KB internal RAM, AlanD core) +0 0 1 1 - 32MHz 65C102 ( 64KB internal RAM, AlanD core) +0 1 0 0 - 8MHz Z80 ( 64KB external RAM, T80 core) +0 1 0 1 - 32MHz Z80 ( 64KB internal RAM, NextZ80 core) +0 1 1 0 - 56MHz Z80 ( 64KB internal RAM, NextZ80 core) +0 1 1 1 - 112MHz Z80 ( 64KB internal RAM, NextZ80 core) +1 0 0 0 - 16Mhz 80286 (896KB external RAM, Zet core) +1 0 0 1 - 4MHz 6809 ( 64KB external RAM, SYS09 core) +1 0 1 0 - 16MHz 68000 ( 1MB external RAM, TG68 core) +1 0 1 1 - 32MHz PDP11 ( 64KB internal RAM, PDP2011 core) +1 1 0 0 - 32MHz ARM2 ( 2MB external RAM, Amber23 core) +1 1 0 1 - 32MHz 32016 ( 2MB external RAM, m32632 core) +1 1 1 0 - Null / SPI ( Raspberry Pi soft core) +1 1 1 1 - BIST ( for manufacturing test purposes) diff --git a/gen_mcs.sh b/gen_mcs.sh index 38d65af..7f8e49a 100755 --- a/gen_mcs.sh +++ b/gen_mcs.sh @@ -4,17 +4,17 @@ # The S25FL032P has space for ~12 designs if they are uncompressed # # multiboot loader - 0x000000 - working/ICAP_reboot.bit -# design 0000 - 0x054000 - working/LX9CoPro6502.bit -# design 0001 - 0x0a8000 - working/LX9CoProZ80.bit -# design 0010 - 0x0fc000 - working/LX9CoPro6809.bit -# design 0011 - 0x150000 - working/LX9CoPro80186.bit -# design 0100 - 0x1a4000 - working/LX9CoProSPI.bit -# design 0101 - 0x348000 - working/LX9CoPro68000.bit -# design 0110 - 0x2f4000 - working/LX9CoProNull.bit -# design 0111 - 0x2a0000 - working/LX9CoProPDP11.bit -# design 1000-1011 - 0x1f8000 - working/LX9CoPro6502fast.bit (32/16/8/4MHz) -# design 1100-1110 - 0x24c000 - working/LX9CoProZ80fast.bit(36/24/12) -# design 1111 - 0x39c000 - working/LX9CoProARM2.bit +# design 0000-0011 - 0x054000 - working/LX9CoPro6502fast.bit (4/8/16/32MHz) +# design 0100 - 0x0a8000 - working/LX9CoProZ80.bit (8MHz) +# design 0101-0111 - 0x0fc000 - working/LX9CoProZ80fast.bit (16/56/112MHz) +# design 1000 - 0x150000 - working/LX9CoPro80186.bit +# design 1001 - 0x1a4000 - working/LX9CoPro6809.bit +# design 1010 - 0x1f8000 - working/LX9CoPro68000.bit +# design 1011 - 0x24c000 - working/LX9CoProPDP11.bit +# design 1100 - 0x2a0000 - working/LX9CoProARM2.bit +# design 1101 - 0x2f4000 - working/LX9CoPro32016.bit +# design 1110 - 0x348000 - working/LX9CoProSPI.bit +# design 1111 - 0x39c000 - working/LX9Co_BIST.bit NAME=multiboot/LX9CoProCombined_$(date +"%Y%m%d_%H%M")_$USER @@ -22,17 +22,17 @@ mkdir -p multiboot promgen \ -u 0 working/ICAP_reboot.bit \ --u 54000 working/LX9CoPro6502.bit \ +-u 54000 working/LX9CoPro6502fast.bit \ -u A8000 working/LX9CoProZ80.bit \ --u FC000 working/LX9CoPro6809.bit \ +-u FC000 working/LX9CoProZ80fast.bit \ -u 150000 working/LX9CoPro80186.bit \ --u 1A4000 working/LX9CoProSPI.bit \ --u 1F8000 working/LX9CoPro6502fast.bit \ --u 24C000 working/LX9CoProZ80fast.bit \ --u 2A0000 working/LX9CoProPDP11.bit \ --u 2F4000 working/LX9CoProNull.bit \ --u 348000 working/LX9CoPro68000.bit \ --u 39C000 working/LX9CoProARM2.bit \ +-u 1A4000 working/LX9CoPro6809.bit \ +-u 1F8000 working/LX9CoPro68000.bit \ +-u 24C000 working/LX9CoProPDP11.bit \ +-u 2A0000 working/LX9CoProARM2.bit \ +-u 2F4000 working/LX9CoPro32016.bit \ +-u 348000 working/LX9CoProSPI.bit \ +-u 39C000 working/LX9Co_BIST.bit \ -o $NAME.mcs -p mcs -w -spi -s 8192 rm -f $NAME.cfi $NAME.prm diff --git a/ise_build_all.tcl b/ise_build_all.tcl index c3ec086..812bf31 100755 --- a/ise_build_all.tcl +++ b/ise_build_all.tcl @@ -2,41 +2,44 @@ project open LX9Co.xise process run "Generate Programming File" project close -project open LX9Co-6502.xise +#project open LX9Co-6502.xise +#process run "Generate Programming File" +#project close +project open LX9Co-6502fast.xise process run "Generate Programming File" project close project open LX9Co-z80.xise process run "Generate Programming File" project close -project open LX9Co-6809.xise +project open LX9Co-z80fast.xise process run "Generate Programming File" project close project open LX9Co-x86.xise process run "Generate Programming File" project close -project open LX9Co-BIST.xise -process run "Generate Programming File" -project close -project open LX9Co-6502fast.xise +project open LX9Co-6809.xise process run "Generate Programming File" project close -project open LX9Co-z80fast.xise +project open LX9Co-68000.xise process run "Generate Programming File" project close project open LX9Co-PDP11.xise process run "Generate Programming File" project close -project open LX9Co-68000.xise +project open LX9Co-ARM2.xise process run "Generate Programming File" project close -project open LX9Co-Null.xise +project open LX9Co-32016.xise process run "Generate Programming File" project close project open LX9Co-SPI.xise process run "Generate Programming File" project close -project open LX9Co-ARM2.xise +project open LX9Co-BIST.xise process run "Generate Programming File" project close +#project open LX9Co-Null.xise +#process run "Generate Programming File" +#project close exit diff --git a/ise_clean_all.tcl b/ise_clean_all.tcl index fdf72ac..d458839 100755 --- a/ise_clean_all.tcl +++ b/ise_clean_all.tcl @@ -2,40 +2,43 @@ project open LX9Co.xise project clean project close -project open LX9Co-6502.xise +#project open LX9Co-6502.xise +#project clean +#project close +project open LX9Co-6502fast.xise project clean project close project open LX9Co-z80.xise project clean project close -project open LX9Co-6809.xise +project open LX9Co-z80fast.xise project clean project close project open LX9Co-x86.xise project clean project close -project open LX9Co-BIST.xise -project clean -project close -project open LX9Co-6502fast.xise +project open LX9Co-6809.xise project clean project close -project open LX9Co-z80fast.xise +project open LX9Co-68000.xise project clean project close project open LX9Co-PDP11.xise project clean project close -project open LX9Co-68000.xise +project open LX9Co-ARM2.xise project clean project close -project open LX9Co-Null.xise +project open LX9Co-32016.xise project clean project close project open LX9Co-SPI.xise project clean project close -project open LX9Co-ARM2.xise +project open LX9Co-BIST.xise project clean project close +#project open LX9Co-Null.xise +#project clean +#project close exit diff --git a/src/ICAP_core.v b/src/ICAP_core.v index 1bd16ff..564d1ef 100644 --- a/src/ICAP_core.v +++ b/src/ICAP_core.v @@ -330,21 +330,22 @@ module ICAP_core case (design_num) 5'b10000: icap_din = 16'h0000; 5'b00000: icap_din = 16'h4000; - 5'b00001: icap_din = 16'h8000; - 5'b00010: icap_din = 16'hC000; - 5'b00011: icap_din = 16'h0000; - 5'b00100: icap_din = 16'h4000; - 5'b00101: icap_din = 16'h8000; - 5'b00111: icap_din = 16'h0000; - 5'b01000: icap_din = 16'h8000; - 5'b01001: icap_din = 16'h8000; + 5'b00001: icap_din = 16'h4000; + 5'b00010: icap_din = 16'h4000; + 5'b00011: icap_din = 16'h4000; + 5'b00100: icap_din = 16'h8000; + 5'b00101: icap_din = 16'hC000; + 5'b00110: icap_din = 16'hC000; + 5'b00111: icap_din = 16'hC000; + 5'b01000: icap_din = 16'h0000; + 5'b01001: icap_din = 16'h4000; 5'b01010: icap_din = 16'h8000; - 5'b01011: icap_din = 16'h8000; - 5'b01100: icap_din = 16'hC000; - 5'b01101: icap_din = 16'hC000; - 5'b01110: icap_din = 16'hC000; + 5'b01011: icap_din = 16'hC000; + 5'b01100: icap_din = 16'h0000; + 5'b01101: icap_din = 16'h4000; + 5'b01110: icap_din = 16'h8000; // The Null Co Processor 5'b01111: icap_din = 16'hC000; - default: icap_din = 16'h4000; + default: icap_din = 16'h8000; // The Null Co Processor endcase end @@ -366,21 +367,22 @@ module ICAP_core case (design_num) 5'b10000: icap_din = 16'h0300; 5'b00000: icap_din = 16'h0305; - 5'b00001: icap_din = 16'h030a; - 5'b00010: icap_din = 16'h030f; - 5'b00011: icap_din = 16'h0315; - 5'b00100: icap_din = 16'h031a; - 5'b00101: icap_din = 16'h0334; - 5'b00111: icap_din = 16'h032a; - 5'b01000: icap_din = 16'h031f; - 5'b01001: icap_din = 16'h031f; + 5'b00001: icap_din = 16'h0305; + 5'b00010: icap_din = 16'h0305; + 5'b00011: icap_din = 16'h0305; + 5'b00100: icap_din = 16'h030a; + 5'b00101: icap_din = 16'h030f; + 5'b00110: icap_din = 16'h030f; + 5'b00111: icap_din = 16'h030f; + 5'b01000: icap_din = 16'h0315; + 5'b01001: icap_din = 16'h031a; 5'b01010: icap_din = 16'h031f; - 5'b01011: icap_din = 16'h031f; - 5'b01100: icap_din = 16'h0324; - 5'b01101: icap_din = 16'h0324; - 5'b01110: icap_din = 16'h0324; + 5'b01011: icap_din = 16'h0324; + 5'b01100: icap_din = 16'h032a; + 5'b01101: icap_din = 16'h032f; + 5'b01110: icap_din = 16'h0334; // The Null/SPI Co Processor 5'b01111: icap_din = 16'h0339; - default: icap_din = 16'h032f; // The Null Co Processor + default: icap_din = 16'h0334; // The Null/SPI Co Processor endcase end diff --git a/src/LX9Co_6SLX25.ucf b/src/LX9Co_6SLX25.ucf new file mode 100644 index 0000000..5cdbcd2 --- /dev/null +++ b/src/LX9Co_6SLX25.ucf @@ -0,0 +1,99 @@ +NET "fastclk" IOSTANDARD = LVCMOS33 ; +NET "h_phi2" IOSTANDARD = LVCMOS33 ; + +NET "fastclk" TNM_NET = fastclk; +TIMESPEC TS_fastclk = PERIOD "fastclk" 31.25 ns HIGH 50%; +NET "h_phi2" TNM_NET = h_phi2; +TIMESPEC TS_h_phi2 = PERIOD "h_phi2" 500 ns HIGH 50%; + +PIN "inst_dcm/CLKFX_BUFG_INST.O" CLOCK_DEDICATED_ROUTE = FALSE; +PIN "h_phi2_BUFGP/BUFG.O" CLOCK_DEDICATED_ROUTE = FALSE; + +NET "h_cs_b" IOSTANDARD = LVCMOS33 ; + +NET "h_rdnw" IOSTANDARD = LVCMOS33 ; +NET "h_rst_b" IOSTANDARD = LVCMOS33 ; + +NET "h_addr<0>" IOSTANDARD = LVCMOS33 ; +NET "h_addr<1>" IOSTANDARD = LVCMOS33 ; +NET "h_addr<2>" IOSTANDARD = LVCMOS33 ; + +NET "h_irq_b" IOSTANDARD = LVCMOS33 ; # Not connected + +NET "h_data<0>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<1>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<2>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<3>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<4>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<5>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<6>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "h_data<7>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; + +NET "ram_cs" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_lb_b" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_oe" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_ub_b" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_wr" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<0>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<1>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<2>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<3>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<4>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<5>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<6>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<7>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<8>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<9>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<10>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<11>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<12>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<13>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<14>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<15>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<16>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<17>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_addr<18>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<0>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<1>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<2>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<3>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<4>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<5>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<6>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<7>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<8>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<9>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<10>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<11>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<12>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<13>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<14>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<15>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<16>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<17>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<18>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<19>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<20>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<21>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<22>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<23>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<24>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<25>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<26>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<27>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<28>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<29>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<30>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "ram_data<31>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<1>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<2>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<3>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<4>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<5>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<6>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<7>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "test<8>" IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "sw<0>" IOSTANDARD = LVCMOS33 ; +NET "sw<1>" IOSTANDARD = LVCMOS33 ; +NET "sw<2>" IOSTANDARD = LVCMOS33 ; +NET "sw<3>" IOSTANDARD = LVCMOS33 ; diff --git a/src/LX9Co_CoPro32016.v b/src/LX9Co_CoPro32016.v new file mode 100644 index 0000000..22444de --- /dev/null +++ b/src/LX9Co_CoPro32016.v @@ -0,0 +1,378 @@ +`define CONFIG_SWITCHES 32'h0 + +module LX9CoPro32016 ( + input fastclk, + + // GOP Signals + output[8:1] test, + input [3:0] sw, + + // Tube signals + input h_phi2, + input [2:0] h_addr, + inout [7:0] h_data, + input h_rdnw, + input h_cs_b, + input h_rst_b, + output h_irq_b, + + // Ram Signals + output reg ram_ub_b, + output reg ram_lb_b, + output reg ram_cs, + output reg ram_oe, + output reg ram_wr, + output reg [18:0] ram_addr, + inout [31:0] ram_data +); + + wire clk; + reg rst_reg; + reg nmi_reg; + reg irq_reg; + + wire [2:0] p_addr; + wire p_cs_b; + wire [7:0] p_data_in; + wire [7:0] p_data_out; + wire p_rd_b; + wire p_wr_b; + wire p_rst_b; + wire p_nmi_b; + wire p_irq_b; + + wire IO_WR; + wire IO_RD; + wire [31:0] IO_A; + wire [3:0] IO_BE; + wire [31:0] IO_DI; + wire [31:0] IO_Q; + wire IO_READY; + + wire ram_enable; + wire rom_enable; + wire tube_enable; + wire config_enable; + + reg [31:0] ram_dout; + wire [31:0] rom_dout; + + reg bootmode; + reg rd_rdy; + + wire [3:0] status; + wire [7:0] statsigs; + + ICAP_config inst_ICAP_config ( + .fastclk(fastclk), + .sw_in (sw), + .sw_out (), + .h_addr (h_addr), + .h_cs_b (h_cs_b), + .h_data (h_data), + .h_phi2 (h_phi2), + .h_rdnw (h_rdnw), + .h_rst_b(h_rst_b) + ); + + assign clk = fastclk; + + M32632 cpu ( + + // ++++++++++ Basic Signals + .BCLK(clk), // input + .MCLK(~clk), // input + .WRCFG(1'b1), // input + .BRESET(rst_reg), // input + .NMI_N(nmi_reg), // input + .INT_N(irq_reg), // input + .STATUS(status), // output + .ILO(), // output + .STATSIGS(statsigs), // output + + // +++++++++ General Purpose Interface + .IO_WR(IO_WR), // output + .IO_RD(IO_RD), // output + .IO_A(IO_A), // output + .IO_BE(IO_BE), // output + .IO_DI(IO_DI), // output + .IO_Q(IO_Q), // input + .IO_READY(IO_READY), // input + + // +++++++++ DRAM Interface In + .ENDRAM(1'b0), // input + .IC_MDONE(1'b0), // input + .DC_MDONE(1'b0), // input + .ENWR(1'b0), // input + .WAMUX(1'b0), // input + .WADDR(10'b0), // input + .DRAM_Q(32'b0), // input + .DWCTRL(3'b0), // input + .IWCTRL(3'b0), // input + + // +++++++++ DRAM Interface Out + .IC_ACC(), + .IDRAM_ADR(), // output + .DC_ACC(), // output + .DC_WR(), // output + .DRAM_ADR(), // output + .DRAM_DI(), // output + + // +++++++++ DMA Interface + .HOLD(1'b1), // input + .HLDA(), // output + .FILLRAM(1'b0), // input + .DMA_AA(24'b0), // input + + // ++++++++++ Coprocessor Interface + .COP_GO(), // output + .COP_OP(), // output + .COP_OUT(), // output + .COP_DONE(1'b0), // input + .COP_IN(64'b0) // input + ); + + assign IO_Q = ram_enable ? ram_dout : + rom_enable ? rom_dout : + tube_enable ? {p_data_out, p_data_out, p_data_out, p_data_out} : + config_enable ? 32'b0 : + 32'b0; + + // Memory Map during booting + // 000000-FFFFFF ROM (32KB, repeating) + + // Memory Map after booting + // 000000-1FFFFF RAM (2MB) + // F00000-F3FFFF ROM (32KB, repeating) + // F90000 Config Switches (A is bit 7, H is bit 0, 1=present) + // A - RSVD; B - RSVD; C - RSVD; D - RSVD; + // E - RSVD; F - RSVD; G - MMU; H - FPU; + // FFFFF0-FFFFFE Tube (even bytes) + + assign rom_enable = (IO_RD) & ( bootmode | (IO_A[23:18] == 6'b111100)); + assign ram_enable = (IO_RD | IO_WR) & (!bootmode & (IO_A[23:21] == 3'b000)); + assign tube_enable = (IO_RD | IO_WR) & (!bootmode & (IO_A[23: 4] == 20'hFFFFF)); + assign config_enable = (IO_RD) & (!bootmode & (IO_A[23: 4] == 20'hF9000)); + + // Internal ROM 8Kx32 bits + tuberom_32016 rom( + .clk(clk), + .addr(IO_A[14:2]), + .data(rom_dout) + ); + + // Tube + assign p_data_in = IO_A[1] ? IO_DI[23:16] : IO_DI[7:0]; + assign p_cs_b = !tube_enable; + assign p_addr = IO_A[3:1]; + assign p_wr_b = !IO_WR; + + tube tube_inst( + .h_addr(h_addr), + .h_cs_b(h_cs_b), + .h_data(h_data), + .h_phi2(h_phi2), + .h_rdnw(h_rdnw), + .h_rst_b(h_rst_b), + .h_irq_b(), + .p_addr(p_addr), + .p_cs_b(p_cs_b), + .p_data_in(p_data_in), + .p_data_out(p_data_out), + .p_rdnw(p_wr_b), + .p_phi2(clk), + .p_rst_b(p_rst_b), + .p_nmi_b(p_nmi_b), + .p_irq_b(p_irq_b) + ); + + always @(posedge clk) + begin + rst_reg <= p_rst_b; + nmi_reg <= p_nmi_b; + irq_reg <= p_irq_b; + rom_rdy <= IO_RD & rom_enable & ~rom_rdy; + if (!rst_reg) + bootmode <= 1'b1; + else if (IO_RD & (IO_A[23:18] == 6'b111100)) + bootmode <= 1'b0; + end + + assign IO_READY = ram_enable ? ram_rdy : // Ram controlled by state machine + rom_enable ? (IO_WR | rom_rdy) : // Rom has 1 cycle rs latency + (IO_WR | IO_RD); // Everying else is immediate + + // Note, this signal not actually connected to the tube connector on the PCB + assign h_irq_b = 1; + + //---------------------------------------------------------------------------- + // State Machine machine performing read-modify-write cycles + //---------------------------------------------------------------------------- + + // External RAM signals + // in spite of the naming, these are all active low + + parameter rd_latency = 1; // 0 .. 7, must be odd or m32632 messes up + parameter wr_latency = 1; // 0 .. 7 + parameter rmw_rd_latency = 1; // 0 .. 7 + parameter rmw_wr_latency = 1; // 0 .. 7 + + parameter s_idle = 0; + parameter s_read = 1; + parameter s_read_modify_write = 2; + parameter s_write = 3; + parameter s_done = 4; + + reg [2:0] state; + reg ram_rdy; + reg rom_rdy; + + // Latency countdown + reg [2:0] lcount; + + // Tri-State-Driver + reg [31:0] wdat; + reg wdat_oe; + assign ram_data = wdat_oe ? wdat : 32'bz; + + // Merged data for byte enables writes + wire [31:0] merged_dat = {(IO_BE[3] ? IO_DI[31:24] : ram_data[31:24]), + (IO_BE[2] ? IO_DI[23:16] : ram_data[23:16]), + (IO_BE[1] ? IO_DI[15: 8] : ram_data[15: 8]), + (IO_BE[0] ? IO_DI[ 7: 0] : ram_data[ 7: 0])}; + + always @(posedge clk) begin + if (~rst_reg) begin + state <= s_idle; + lcount <= 0; + ram_rdy <= 0; + end else begin + case (state) + s_idle: begin + ram_rdy <= 0; + if (ram_enable & IO_RD) begin + ram_cs <= 0; + ram_oe <= 0; + ram_wr <= 1; + ram_addr <= IO_A[20:2]; + ram_ub_b <= 0; + ram_lb_b <= 0; + wdat_oe <= 0; + lcount <= rd_latency; + state <= s_read; + end else if (ram_enable & IO_WR & (IO_BE == 4'b1111)) begin + ram_cs <= 0; + ram_oe <= 1; + ram_wr <= 0; + ram_addr <= IO_A[20:2]; + ram_ub_b <= 0; + ram_lb_b <= 0; + wdat <= IO_DI; + wdat_oe <= 1; + lcount <= wr_latency; + state <= s_write; + end else if (ram_enable & IO_WR) begin + ram_cs <= 0; + ram_oe <= 0; + ram_wr <= 1; + ram_addr <= IO_A[20:2]; + ram_ub_b <= 0; + ram_lb_b <= 0; + wdat_oe <= 0; + lcount <= rmw_rd_latency; + state <= s_read_modify_write; + end else begin + ram_cs <= 1; + ram_oe <= 1; + ram_wr <= 1; + wdat_oe <= 0; + end + end + s_read: begin + if (lcount != 0) begin + lcount <= lcount - 1; + end else begin + ram_cs <= 1; + ram_oe <= 1; + ram_wr <= 1; + ram_dout <= ram_data; + ram_rdy <= 1; + state <= s_done; + end + end + s_read_modify_write: begin + if (lcount != 0) begin + lcount <= lcount - 1; + end else begin + ram_cs <= 0; + ram_oe <= 1; + ram_wr <= 0; + ram_addr <= IO_A[20:2]; + ram_ub_b <= 0; + ram_lb_b <= 0; + wdat <= merged_dat; + wdat_oe <= 1; + lcount <= rmw_wr_latency; + state <= s_write; + end + end + s_write: begin + if (lcount != 0) begin + lcount <= lcount - 1; + end else begin + ram_cs <= 1; + ram_oe <= 1; + ram_wr <= 1; + ram_rdy <= 1; // XXX We could acknoledge write XXX + state <= s_done; // XXX requests 1 cycle ahead XXX + end + end + s_done: begin + ram_rdy <= 0; + state <= s_idle; + end + endcase + end + end + + //---------------------------------------------------------------------------- + // Test outputs + //---------------------------------------------------------------------------- + + // default to hi-impedence, to avoid conflicts with + // a Raspberry Pi connected to the test connector + assign test = 8'bZ; + + //---------------------------------------------------------------------------- + // Test setups for debugging + //---------------------------------------------------------------------------- + + // // For Udo's CPU Test Program + // assign rom_enable = (IO_RD) & (IO_A[23:13] == 11'b00000000000); + // assign ram_enable = (IO_RD | IO_WR) & (IO_A[23:13] != 11'b00000000000); + // assign tube_enable = 0; + // assign config_enable = 0; + + // wire [7:0] trig; + // wire fetchc; + // wire fetchd; + // assign fetchc = IO_RD & (status == 4'b1000); + // assign fetchd = IO_RD & (status == 4'b1010); + // assign trig[5] = fetchc & (IO_A[23:0] == 24'h000000); + // assign trig[4] = fetchc & (IO_A[23:0] == 24'h000A60); + // assign trig[3] = fetchc & (IO_A[23:0] == 24'h001C70); + // assign trig[2] = fetchc & (IO_A[23:0] == 24'h001CA8); + // assign trig[1] = fetchc & (IO_A[23:0] == 24'h001CA9); + // assign trig[0] = fetchc & (IO_A[23:0] == 24'h001CB8); + // assign test = sw[3] ? {rst_reg, fetchc, IO_A[17:12]} : + // sw[2] ? {rst_reg, fetchc, IO_A[11:6]} : + // sw[1] ? {rst_reg, fetchc, IO_A[5:0]} : + // sw[0] ? {rst_reg, fetchc, trig[5:0]} : + // {p_irq_b, p_nmi_b, bootmode, IO_RD, IO_WR, ram_enable, rom_enable, tube_enable}; + // assign test = sw[3] ? {rst_reg, fetchc, fetchd, bootmode, status} : + // sw[2] ? {rst_reg, fetchc, fetchd, IO_A[14:10]} : + // sw[1] ? {rst_reg, ram_enable, IO_RD, IO_WR, ram_cs, ram_oe, ram_wr, ram_rdy} : + // sw[0] ? {rst_reg, tube_enable, p_cs_b, p_wr_b, p_data_in[3:0]} : + // {p_irq_b, p_nmi_b, bootmode, IO_RD, IO_WR, ram_enable, rom_enable, tube_enable}; + +endmodule diff --git a/src/LX9Co_CoPro6502fast.vhd b/src/LX9Co_CoPro6502fast.vhd index acbf3c3..9790a18 100644 --- a/src/LX9Co_CoPro6502fast.vhd +++ b/src/LX9Co_CoPro6502fast.vhd @@ -214,13 +214,13 @@ begin -- Original: Acorn TUBE 65C102 Co-Processor -- Updated: Acorn TUBE 32Mhz 65C102 Co-Pro - digit1 <= x"33" when sw_out(1 downto 0) = "00" else - x"31" when sw_out(1 downto 0) = "01" else + digit1 <= x"33" when sw_out(1 downto 0) = "11" else + x"31" when sw_out(1 downto 0) = "10" else x"30"; - digit2 <= x"32" when sw_out(1 downto 0) = "00" else - x"36" when sw_out(1 downto 0) = "01" else - x"38" when sw_out(1 downto 0) = "10" else + digit2 <= x"32" when sw_out(1 downto 0) = "11" else + x"36" when sw_out(1 downto 0) = "10" else + x"38" when sw_out(1 downto 0) = "01" else x"34"; ram_cs_b <= '0' when p_cs_b = '1' and rom_cs_b = '1' else '1'; @@ -304,13 +304,13 @@ begin if rising_edge(clk_cpu) then clken_counter <= clken_counter + 1; case "00" & sw_out(1 downto 0) is - when x"0" => + when x"3" => cpu_clken <= clken_counter(0); - when x"1" => - cpu_clken <= clken_counter(1) and clken_counter(0); when x"2" => + cpu_clken <= clken_counter(1) and clken_counter(0); + when x"1" => cpu_clken <= clken_counter(2) and clken_counter(1) and clken_counter(0); - when x"3" => + when x"0" => cpu_clken <= clken_counter(3) and clken_counter(2) and clken_counter(1) and clken_counter(0); when others => cpu_clken <= clken_counter(0); diff --git a/src/LX9Co_CoProSPI.ucf b/src/LX9Co_CoProSPI.ucf index 6966668..db6b7da 100644 --- a/src/LX9Co_CoProSPI.ucf +++ b/src/LX9Co_CoProSPI.ucf @@ -60,9 +60,9 @@ NET "ram_data<4>" LOC = "P5" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = NET "ram_data<5>" LOC = "P2" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; NET "ram_data<6>" LOC = "P1" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; NET "ram_data<7>" LOC = "P143" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; -NET "p_spi_ssel" LOC = "P83" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; -NET "p_spi_sck" LOC = "P82" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; -NET "p_spi_mosi" LOC = "P81" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; +NET "p_spi_ssel" LOC = "P83" | IOSTANDARD = LVCMOS33 | PULLDOWN; +NET "p_spi_sck" LOC = "P82" | IOSTANDARD = LVCMOS33 ; +NET "p_spi_mosi" LOC = "P81" | IOSTANDARD = LVCMOS33 ; NET "p_spi_miso" LOC = "P80" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; NET "p_irq_b" LOC = "P79" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; NET "p_nmi_b" LOC = "P78" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 2 ; diff --git a/src/LX9Co_CoProSPI.vhd b/src/LX9Co_CoProSPI.vhd index e07e99d..0ce00dd 100644 --- a/src/LX9Co_CoProSPI.vhd +++ b/src/LX9Co_CoProSPI.vhd @@ -48,6 +48,11 @@ architecture BEHAVIORAL of LX9CoProSPI is signal h_data_in : std_logic_vector(7 downto 0); signal h_data_out : std_logic_vector(7 downto 0); + signal spi_attached : std_logic := '0'; + signal h_rst_b1 : std_logic; + signal h_rst_b2 : std_logic; + signal h_rst_b3 : std_logic; + signal h_phi2_b : std_logic; begin @@ -66,9 +71,11 @@ begin h_rdnw => h_rdnw, h_rst_b => h_rst_b ); + + h_phi2_b <= not h_phi2; inst_CoProSPI : entity work.CoProSPI port map ( - h_clk => not h_phi2, + h_clk => h_phi2_b, h_cs_b => h_cs_b, h_rdnw => h_rdnw, h_addr => h_addr, @@ -96,8 +103,26 @@ begin ); h_data_in <= h_data; - h_data <= h_data_out when h_rdnw = '1' else (others => 'Z'); - + h_data <= h_data_out when spi_attached = '1' and h_cs_b = '0' and h_rdnw = '1' and h_phi2 = '1' else + x"FE" when spi_attached = '0' and h_cs_b = '0' and h_rdnw = '1' and h_phi2 = '1' else + (others => 'Z'); + +-------------------------------------------------------- +-- SPI / Null mode selection +-------------------------------------------------------- + + process(fastclk) + begin + if rising_edge(fastclk) then + h_rst_b1 <= h_rst_b; + h_rst_b2 <= h_rst_b1; + h_rst_b3 <= h_rst_b2; + if h_rst_b3 = '0' and h_rst_b2 = '1' then + spi_attached <= p_spi_ssel; + end if; + end if; + end process; + -------------------------------------------------------- -- external Ram unused -------------------------------------------------------- @@ -112,7 +137,7 @@ begin -------------------------------------------------------- -- test signals -------------------------------------------------------- - p_test <= h_rst_b; + p_test <= spi_attached; end BEHAVIORAL; diff --git a/src/LX9Co_CoProZ80fast.vhd b/src/LX9Co_CoProZ80fast.vhd index 532bd1b..76a0271 100644 --- a/src/LX9Co_CoProZ80fast.vhd +++ b/src/LX9Co_CoProZ80fast.vhd @@ -215,17 +215,17 @@ begin -- Original: Acorn TUBE Z80 64k 1.21 -- Updated: Acorn TUBE Z80 112 Mhz - digit1 <= x"31" when sw_out(1 downto 0) = "00" else + digit1 <= x"31" when sw_out(1 downto 0) = "11" else x"06"; - digit2 <= x"31" when sw_out(1 downto 0) = "00" else - x"35" when sw_out(1 downto 0) = "01" else - x"33" when sw_out(1 downto 0) = "10" else + digit2 <= x"31" when sw_out(1 downto 0) = "11" else + x"35" when sw_out(1 downto 0) = "10" else + x"33" when sw_out(1 downto 0) = "01" else x"31"; - digit3 <= x"32" when sw_out(1 downto 0) = "00" else - x"36" when sw_out(1 downto 0) = "01" else - x"32" when sw_out(1 downto 0) = "10" else + digit3 <= x"32" when sw_out(1 downto 0) = "11" else + x"36" when sw_out(1 downto 0) = "10" else + x"32" when sw_out(1 downto 0) = "01" else x"36"; ram_cs_b <= '0' when cpu_mreq_n = '0' and rom_cs_b = '1' else '1'; @@ -307,19 +307,19 @@ begin begin if rising_edge(cpu_clk) then case "00" & sw_out(1 downto 0) is - when x"0" => + when x"3" => if (clken_counter = 1) then clken_counter <= (others => '0'); else clken_counter <= clken_counter + 1; end if; - when x"1" => + when x"2" => if (clken_counter = 3) then clken_counter <= (others => '0'); else clken_counter <= clken_counter + 1; end if; - when x"2" => + when x"1" => if (clken_counter = 6) then clken_counter <= (others => '0'); else diff --git a/src/ROM/tuberom_32016.v b/src/ROM/tuberom_32016.v new file mode 100644 index 0000000..13271c7 --- /dev/null +++ b/src/ROM/tuberom_32016.v @@ -0,0 +1,16 @@ +module tuberom_32016 ( + input clk, + input [12:0] addr, + output reg [31:0] data +); + + reg [31:0] rom[0:8191]; + + always @(posedge clk) + begin + data <= rom[addr]; + end + + initial $readmemh("tuberom_32016_200.dat", rom); + +endmodule diff --git a/src/ROM/tuberom_32016_061.dat b/src/ROM/tuberom_32016_061.dat new file mode 100644 index 0000000..9b18914 --- /dev/null +++ b/src/ROM/tuberom_32016_061.dat @@ -0,0 +1,8192 @@ +f0c0aa7f +0000c007 +00000000 +00000000 +00000000 +000017f4 +00000000 +00000000 +00f00000 +00000000 +00000000 +00000000 +00f00000 +00000000 +98860018 +00400000 +00100042 +00000ae1 +00101356 +0010135e +00101365 +0010136c +00100e24 +00101373 +0010137a +00101381 +00101388 +0010138f +001013b9 +001013c2 +001013cb +001013d4 +001013dc +001013e4 +001013ec +001013f4 +001013fc +00101404 +0010140c +00100bd0 +00100bd0 +00100bd0 +00100bd0 +00100bd0 +00100bd0 +00100bd0 +00100bd2 +00100bd0 +00100bd0 +00100bd0 +00100bd0 +fdff0bd0 +0101e0f2 +000007fc +00000000 +00000000 +00000000 +00000000 +00000000 +01058000 +6c6c6914 +6c616765 +65766520 +6e20746e +65626d75 +0e010072 +656c6946 +746f6e20 +756f6620 +0101646e +5f4b541d +76697270 +67656c69 +61632065 +64656c6c +6f726620 +7375206d +01027265 +7474412b +74706d65 +206f7420 +69646f6d +70207966 +69766972 +6567656c +20666f20 +705f4b54 +69766972 +6567656c +55250103 +6f6e6b6e +53206e77 +72204356 +72656665 +65636e65 +20796220 +705f4b54 +69766972 +6567656c +49200104 +67656c6c +6c206c61 +2064616f +65747461 +2074706d +54207962 +534f5f4b +1b494c43 +73450601 +65706163 +450b01fe +6f20646e +69662066 +01ff656c +79654b0b +6d697420 +74756f65 +0dd705d7 +2881d057 +024818ce +a7040694 +098f08d0 +1700000e +ce2881d0 +97004059 +b857000e +0012b817 +7006a574 +05547c9a +74001272 +9a7406a5 +00a5547c +07a57476 +547c9a74 +a57476a8 +7c9a7407 +7476a814 +001207a0 +f880d4af +c080dea7 +a044f480 +742d5a80 +9a7406a5 +04a5547c +06a57476 +547c9a74 +a5747615 +7c9a7406 +74760d54 +9a7407a5 +a898ce7c +20a17c76 +a17c0012 +085cce20 +10d843ee +ef7d228a +001204d8 +001c0016 +ffffff84 +ffffff82 +0012105f +9480d097 +152f0012 +a5740012 +7c9a7406 +7606a554 +7406a574 +15547c9a +06a57476 +547c9a74 +a574761d +7c9a7406 +44760d54 +071a9da0 +1220a17c +07a57400 +147c9a74 +a57476a8 +7c9a7407 +76a898ce +954e10d7 +a57408a0 +7c9a7407 +3476a894 +d43c07a0 +a17d2481 +00122000 +2000a37d +00100012 +02050005 +040e0805 +00050101 +0d101010 +10800800 +00050005 +00000005 +00050905 +0d101008 +8008800d +f880d4af +8b80dea7 +a044f480 +88800a00 +7406a574 +a5547c9a +a5747608 +7c9a7406 +04760d54 +08aa800d +005018ce +a04412ea +5f04ba14 +0858ce08 +d9e018ce +a5749ebf +7c9a7406 +1c760554 +74100a00 +9a7406a5 +50e5547c +07cc767f +800d0475 +18ce08aa +08ea0150 +d9e018ce +a57487bf +7c9a7406 +1c760554 +74100a00 +9a7407a5 +50af147c +07cc7f76 +80d05f75 +00a17df4 +7d001220 +122000a3 +06a57400 +547c9a74 +74760aa5 +9a7406a5 +0655547c +06a57476 +547c9a74 +74760555 +9a7406a5 +0455547c +06a57476 +547c9a74 +747607a5 +9a7406a5 +00a5547c +07a57476 +147c9a74 +d05f76a8 +001cf480 +dea7107a +2881b1bd +7cd0bd02 +001220a3 +74005017 +9a7407a5 +76aa147c +04008f00 +1a7f0da2 +e300d770 +1f8f0050 +1220a17c +80d4af00 +34dea7f8 +a574f480 +7c9a7406 +7610a554 +7406a574 +15547c9a +06a57476 +547c9a74 +a574760d +7c9a7407 +5f76a814 +7df480d0 +122000a1 +00a37d00 +af001220 +a7f880d4 +f4803dde +7406a574 +a5547c9a +a574760e +7c9a7406 +74761554 +9a7407a5 +76a8147c +f480d05f +7407a574 +58ce7c9a +a03476a8 +97099a07 +010000a6 +001200fe +2000a37d +d4af0012 +dea7f880 +f4808280 +7406a574 +a5547c9a +a5747612 +7c9a7406 +1c760d54 +741e1a08 +9a7406a5 +7615547c +7407a574 +a8147c9a +80d05f76 +00a17df4 +1f001220 +141c0a18 +a0070050 +0d000000 +a574110a +7c9a7406 +8f760554 +ea108f1f +06a57464 +547c9a74 +74760da5 +9a7407a5 +a858ce7c +80d05f76 +0a081cf4 +00a17d08 +a7001220 +81d6bbde +9fbc0228 +2000a37d +d4af0012 +dea7f880 +f4805980 +7406a574 +a5547c9a +a574760c +7c9a7406 +5f761554 +a0c34e02 +06a57408 +547c9a74 +07cf761d +06a57473 +547c9a74 +a574760d +7c9a7407 +5f76a854 +a0d74e02 +07a57408 +d47c9a74 +07cf76a8 +80d05f73 +00a17df4 +7d001220 +122000a3 +271dd700 +17a880d0 +2a170022 +08321704 +af0c3a17 +a7f880d4 +809380de +06a574f4 +547c9a74 +d77614a5 +000000a0 +06a57410 +547c9a74 +767f43e5 +d7751fcf +181f00c8 +5014190a +0da00400 +a574110a +7c9a7406 +8f760554 +ea108f1f +06a57467 +547c9a74 +74760da5 +9a7406a5 +760d547c +7407a574 +a8547c9a +80d05f76 +00a06bf4 +277f0000 +d7a880d0 +000000a0 +07a57410 +147c9a74 +7f7643af +17751fcf +41570041 +08419704 +d70c41d7 +20a17cb8 +b8d70012 +2000a37d +d4af0012 +dea7f880 +f4808d80 +7406a574 +a5547c9a +0e947616 +d067a880 +1254a880 +021a5701 +57062257 +a0140a2a +06a5740e +547c9a74 +767f48e5 +147507cc +a5740da0 +7c9a7407 +7648af14 +7507cc00 +170a4957 +48d70649 +4898ce02 +07a57401 +147c9a74 +a57476a8 +7c9a7407 +76a858ce +a880d504 +0410aa01 +04a880d5 +201f094a +204e00bc +07a03400 +f480d05f +0012048a +0000a697 +7c00fe01 +001220a3 +98ce0762 +10cf0048 +14088f0b +bb020048 +7817cf06 +0012e072 +481405d5 +0a001c00 +f3ba0214 +1a0da004 +0aa01408 +8fe8ba02 +1569ea08 +d70012b8 +04c8570d +4e675c02 +b8570401 +0dd70012 +0204c857 +014e674d +02b85704 +12000d64 +ce036200 +0f20a058 +c8082e0e +a0000404 +39050430 +038c047a +1fa4ba02 +726a1a08 +620012c0 +a058ce03 +625eea08 +a058ce03 +6256ea10 +a058ce03 +824eea18 +c0670c02 +02090274 +409265bf +17620012 +0aa118ce +001f25d4 +33ce0097 +20b7ce20 +c015f04e +004f30a5 +d4057a72 +48a72da5 +dfb86701 +06000e07 +6872057f +0002744e +0012b817 +f9c0a85c +d8670000 +105f52b8 +0e08a827 +a4ef0003 +00010000 +60b8d827 +18ce076f +00f9c0a8 +03a02800 +04d8e77c +17120d08 +ea000b0e +010b0e11 +0b0e0cea +0e07ea02 +02ea030b +0200a017 +00570000 +11a0484e +085f048a +d7004097 +a2170048 +aaaa5555 +aaa25700 +005555aa +55004507 +1aaaaa55 +004d073a +5555aaaa +a217311a +5555aaaa +55a25700 +00aaaa55 +aa004507 +1a5555aa +004d071a +aaaa5555 +1217111a +001a5700 +0200a003 +bfea0000 +001217a4 +57001a57 +00a06300 +ef000400 +100d570c +e710ade7 +003205dd +90800697 +0000a063 +0e970010 +a6979880 +00010000 +be029480 +4e415094 +41524f44 +30323320 +76203631 +69737265 +30206e6f +0d31362e +80d01700 +62be0290 +6f6d654d +73207972 +20657a69 +4e00203d +02f6a017 +be02a8be +696b2058 +79626f6c +0d736574 +0c810200 +0d00a697 +3082020a +0000a697 +34820000 +0000a697 +388200c0 +3c82d05c +1081d15c +c681dea7 +d0dff480 +a37dec80 +a5740008 +7c9a7006 +7200a554 +7407a574 +ae947c9a +5f008176 +84f480d0 +108101a6 +ec80d05f +81020d0a +00a6843b +800a0c81 +12a69764 +81785634 +80a68404 +811a0081 +80d01745 +678002d8 +973b819a +000000a6 +97348100 +843c8106 +348102a6 +8002050a +8cd8677f +81d047bf +67190a3c +0cef00d0 +3481d057 +0008a5d5 +0001a5d5 +3c81d5d7 +d0570042 +a0473481 +00000000 +ea948c0a +a687918c +01efcdab +bf1a0481 +81d0179f +00a69708 +81010000 +aabfea34 +68064054 +a0440da0 +ce231a09 +07074058 +432901a7 +161a0028 +e01c0a0f +8f060a01 +0379ea08 +7c0541e0 +001220a3 +1220a17c +64800200 +28020f02 +02448002 +80028980 +6700126f +a797b6d8 +17f082d0 +000000a0 +00030e0f +2c81d05f +3081d05f +d05c0012 +d05f8480 +a6978880 +61000000 +d05ff080 +d0dff480 +d0df1c81 +00121881 +32b6dea7 +d8679c80 +d0a700b6 +a0172c83 +10000000 +1200030e +81a85f00 +81a85f00 +81a85f04 +81a85f08 +10ad2f0c +1200ad2f +83d02700 +12076f2c +5c0edc00 +e21fdc10 +1698ce06 +00120c81 +4ab6d867 +6c83d0a7 +0000a017 +030e0800 +97001200 +000000a6 +27348100 +0361b5d8 +026db5d8 +a69719bf +01efcdab +dea70481 +08814eb5 +58b5de83 +be8a0881 +8bdea7a9 +27088173 +ea6d8bd8 +d0679cbe +a0974481 +28000000 +02e21fe2 +bfea04e2 +07a574b9 +740b8a7c +8a7007a5 +6188ea0b +ea328102 +a57c3484 +7407620c +9a7007a5 +72a8147c +da000504 +06a03416 +8480d43c +5710cc3f +000000a6 +80ea14fd +07a574a1 +740d8a70 +9a7c07a5 +f9800276 +58ce71ea +740c72ae +8a7007a5 +07a5740d +02769a7c +71eae380 +72ae58ce +07a57410 +740d8a70 +9a7c07a5 +cd800276 +18ce71ea +065772a8 +06050414 +7d4f804a +1204d8ef +24001b00 +34002c00 +44003c00 +7fe07200 +eaf082d0 +e0724b80 +f482d07f +724280ea +82d07fe0 +7239eaf8 +82d07fe0 +7231eafc +83d07fe0 +7229ea00 +83d07fe0 +7221ea04 +83d07fe0 +7219ea08 +83d07fe0 +7211ea10 +00a6b4e0 +089a3081 +1c83d07f +a57c02ea +5a83eaf4 +0f820032 +08a37d1e +daa05400 +185c105c +15e206e2 +3c0d0a1b +55203c3c +7474616e +75626972 +6c626174 +72652065 +20726f72 +020cc054 +15e260bb +203a2003 +a762c067 +1fe21ea8 +15e202e2 +3e3e3e05 +f0920d0a +07620032 +9500ad2f +835613a6 +a818ce32 +8006947e +000504a0 +741181ca +9a7c07a5 +7eae947c +029ca480 +5cfd800a +07a5740a +d47c9a7c +0fcc7ead +00bd5777 +8100ae97 +01a68440 +0b1aec80 +8000ae97 +80d05cd8 +d8ee95ec +32834481 +1c81d09c +a034070a +041d8a00 +80da0605 +0405045d +d0dc060a +a5741081 +7c9a7c07 +ea7ea814 +d0dfaa80 +009c2081 +019c2d0a +a014320a +7ca81c80 +a81c7dca +78a81c7e +ae947dca +0f14817a +78a81c09 +ae947dca +cc14817a +80ea6a07 +0da69577 +ea3283f1 +a695acbf +3283f80d +dca3bfea +571081d0 +a01400a8 +80d31c80 +1a070aa0 +00000031 +ca7ca81c +7ea81c7d +ca78a81c +004d547d +1c090f7a +7dca78a8 +7a7f4d54 +1c6c07cc +7dca78a8 +ea7a0554 +00000026 +ca7ca81c +7ea81c7d +ca78a81c +7aaa547d +1c090f00 +7dca78a8 +7f7aaa54 +ea6c07cc +12e07202 +00d7df00 +0008a37d +7407a574 +a8547c9a +08d06776 +7407a574 +ae947c9a +a5740076 +7c9a7407 +0076aa54 +481c088f +8f711a7f +08d0a70f +0e971063 +80d01f04 +72190af4 +80d4efe0 +d9beadf8 +ad0008a5 +80d5d7bf +80d05ff4 +e07252f4 +fea5d8ce +d5d7b85f +83d07f00 +1dbeea0c +81eae072 +ce0dc575 +e40dd70d +5613560d +56135613 +00d55413 +00a88f7a +ae940042 +a88f007a +54004200 +547a00d5 +0f7a01d5 +004200a9 +007aae94 +017aae94 +4200a90f +7aae9400 +00421481 +817aae94 +7aae9414 +00421481 +c90f05d7 +08a67404 +ce098a0a +7f048818 +9cae1aea +807f048e +d018cee4 +0ceae480 +c90f05d7 +8818ce04 +06b77f04 +859a6c83 +3c079c64 +48b800b8 +7d0a20a6 +7804d8ef +4a011100 +65033501 +a9037503 +e103d003 +9d055703 +cb04b204 +ed04dc04 +5704fe04 +57017305 +bc055705 +57011f02 +57055705 +57055705 +57055705 +27055705 +40029702 +57055701 +57055705 +57055705 +2c055705 +57055703 +57055705 +57055705 +57055705 +35055705 +6a020101 +20028901 +e802cb03 +ce018201 +9c00c818 +00b83c07 +0a001fb8 +bfead384 +81d01c68 +42041a2c +00a6b400 +808a2c81 +02a6b451 +258a2c81 +0605a674 +0042048a +0000a5d7 +a5d7fb00 +00000000 +0000a5d7 +d07f0000 +a57c1883 +9c0042f4 +0a3881d0 +a5d74380 +fc000000 +0000a5d7 +a5d70000 +00000000 +d07f2e0a +a57c1483 +740042f4 +8a0608a6 +d7004204 +000000a5 +00a5d7fa +d7000000 +000000a5 +83d07f00 +f4a57c20 +d05c0042 +00423881 +7006a574 +0d547c9a +eab81772 +0dd76ebf +c85715d7 +4898ce0c +17088f00 +57100308 +1bea0c06 +040ea695 +b8174283 +494dbfea +0a0001a6 +bfeab817 +d70dd743 +0a101f15 +06a57411 +547c9a70 +8f72004d +7417cf08 +b857b897 +bfeab817 +80d05723 +eab817f0 +a6971abf +02000000 +d0173481 +b9ea0881 +fa0d04a9 +044a80aa +800aff0d +fc0d0444 +18ce1e7a +00a02308 +b4fd0000 +098a00a0 +81068b4e +4e3bea30 +3081069b +18ce34ea +00a02308 +b4fa0000 +0d8a00a0 +81068b4e +81d0dc2c +4e1bea38 +2c81069b +dea714ea +2881e0b0 +58c0b102 +170a20a6 +acbeeab8 +b817143f +74a5beea +58ce00a0 +9a1881d0 +81d0dc08 +5c06ea18 +171881d0 +8cbeeab8 +130a081f +cdaba697 +048101ef +08810e97 +beeab817 +00a69777 +81040000 +00a05734 +ea030000 +0dd734ba +040858ce +154a060d +82d1f017 +d11797f0 +0097f082 +b817b857 +1c49beea +3d800a0d +2c0a0d9c +220a0e1c +2a0a0e9c +110a0f1c +110a0f9c +a658b857 +b8170a20 +df25beea +6747ea0b +42ea08a8 +ea09a867 +a867bdbf +b7bfea0a +ea0ba867 +a867b1bf +abbfea0c +9ab78302 +20a65806 +eab8170a +0dd7f6bd +6a04d087 +04d09705 +101715d7 +d0670897 +00000e08 +9704d05f +17b857b8 +00d0d7b8 +9cd1bdea +1a8480d0 +20a65806 +eab8170a +a674c2bd +278a0a08 +2e0a0044 +f70858ce +9ab7af0e +00a0b430 +8b4e098a +ea6c830e +0e9b4e07 +0c3f6c83 +bdeab817 +afdea797 +022881e1 +18ea99b0 +f6afdea7 +b0022881 +a70dea8e +8119b0de +83b00228 +a65802ea +b8170a20 +ce6dbdea +f9c0a858 +b8170000 +9761bdea +179c800e +58bdeab8 +0a0da044 +06a57410 +547c9a70 +b817720d +5445bdea +a5740aa0 +7c9a7006 +54720d54 +a5740da0 +7c9a7006 +17720d54 +28bdeab8 +15d70dd7 +82d098ce +82d06730 +dcbdea31 +7406a574 +a5547c9a +a5747600 +7c9a7407 +7476a814 +9a7407a5 +a858ce7c +07a03476 +dea70f9a +2881d9af +58f8af02 +170a20a6 +e4bceab8 +9a40b002 +00d05709 +0a20a658 +8100a6b4 +4e0c8a24 +0a00a648 +bceab817 +a6584ec7 +b8170a00 +02bdbcea +099a0db1 +0a20a658 +1700d057 +acbceab8 +2081d05f +ec80d0df +1881d697 +a5741c81 +7c9a7406 +7602a554 +f880d4af +9480dea7 +101ff480 +4814190a +0da00400 +a574110a +7c9a7406 +8f760554 +ea178f08 +06a57467 +547c9a74 +74760da5 +9a7407a5 +76a8147c +1c81d0df +2081d09c +0446800a +070a80a0 +bceab817 +80d01747 +37b702d8 +ce951b8a +17fc800a +f8a57cb8 +fc80d5d5 +0001a5d5 +4081d5d7 +9725bcea +efcdaba6 +97048101 +97088106 +000000a6 +ea348103 +dea7acb6 +2881ceae +5810af02 +170a20a6 +fcbbeab8 +0a20a658 +1700d057 +f0bbeab8 +b20215d7 +9ab897c3 +20a65809 +00d0570a +bbeab817 +d715d7db +bdb1021d +b897b8d7 +a658099a +d0570a20 +eab81700 +b202c2bb +58099a34 +570a20a6 +b81700d0 +02b1bbea +099a50b1 +0a20a658 +1700d057 +a0bbeab8 +9a01b102 +20a65809 +00d0570a +bbeab817 +15b3028f +a658099a +d0570a20 +eab81700 +05d77ebb +ea00a827 +05d74980 +ea04a827 +05d74180 +ea08a827 +2705d739 +32ea0ca8 +a82705d7 +d72bea10 +18a82705 +05d724ea +ea1ca827 +2705d71d +16ea20a8 +a82705d7 +d70fea24 +28a82705 +cf0f08ea +14a82704 +9c80d003 +0045d9ce +0245d9ce +08048dc3 +0812c814 +006c02a0 +3208c817 +49a5d704 +ea034e56 +a5d75580 +034e4d49 +d74c80ea +414254a5 +4380ea03 +5055a5d7 +3aea0346 +4c4ca5d7 +32ea0349 +5643a5d7 +2aea0353 +565aa5d7 +22ea0344 +4c47a5d7 +1aea0346 +5054a5d7 +12ea0342 +5243a5d7 +0aea0354 +4e44a5d7 +02ea0355 +0d0bb302 +2a2a0a0a +7845202a +74706563 +206e6f69 +b8670028 +02bcb202 +2029f0b2 +50207461 +203d2043 +04c81700 +0233b302 +00eaf8b2 +c8a70662 +0257dd0c +a054085f +7207e206 +82051260 +c0a70506 +08c2957b +0257dd00 +a054085f +1407e205 +920b7fc6 +5c031260 +e21fdc10 +62001206 +570817f9 +aa089f09 +bfd9670b +d9f143bf +2d07f680 +00010000 +07df80aa +7548006d +801a5664 +b3a054d5 +d8ce4f02 +b4a05411 +11944702 +691539a0 +00a1010c +a1154eff +04699cf8 +87b780aa +0a348206 +d1e09a80 +26943c82 +a0543c82 +e2105c14 +b3a05406 +38802094 +185c15d4 +a05406e2 +5cb894b4 +1f06e218 +3d800a00 +08a1d54e +68432857 +47185f08 +30da0c1b +7719e5d4 +1b9a181b +0159e094 +08a0954e +68a1b894 +d5388114 +1fe5e715 +8f24bf02 +1fe5e718 +cf1cbf02 +a1d55418 +17df00c0 +16973895 +69c13882 +1469e110 +a5d73dd5 +0e02ffff +d7fcbe02 +02ffffa5 +f3be020f +82046e97 +82d05730 +82069734 +82d09734 +20a17c38 +00129f72 +a37c105f +df77ea20 +5f77ea0f +df73ea0f +436fea0e +5b000001 +56000001 +02487564 +00000d0a +00000000 +cb000000 +000000ff +560000c0 +01487564 +2600000a +6b000000 +0e000000 +0e000034 +20000034 +00404020 +40400810 +48012020 +d01bc900 +3448200d +a9482eb0 +3445200a +04c96068 +482012b0 +481db034 +6220eca9 +6a6a6a34 +60119068 +0cd00ac9 +b0344820 +200da907 +0aa93445 +48ffcb4c +6220eca9 +686a6a34 +572003b0 +a9486034 +346220da +68ff6918 +34778e60 +a234788c +20ffa000 +ac8afff4 +77ae3478 +00006034 +1000a7ed +2f10ad6f +e20cef0d +5f2a0115 +80d0a708 +81d2a7d0 +a2940044 +a29404ea +a2940520 +07e2067f +a37d128a +d4ef0002 +a17d9880 +1d020002 +a0574fea +7e000000 +15e206e2 +450d0a0b +70616373 +0d0a2165 +67bbbfea +974481d0 +08a37d08 +0da28400 +8f060a00 +a378ea10 +d7108f08 +02099711 +808aa180 +00a0c783 +1a020000 +53a28522 +800a0047 +55a28582 +800a0047 +73a2856d +800a0067 +75a28572 +800a0067 +9730575d +03a37d38 +8a08e200 +7d20e20a +120002a1 +7d20e200 +670002a1 +d09708d0 +e202e204 +d5001204 +d5000ba5 +d70001a5 +d5004205 +d5000aa5 +d70001a5 +02004205 +0d0a1fb0 +7373694d +20676e69 +75677261 +746e656d +12000d0a +57001200 +8a170220 +4780027a +41ea5b8a +0a022057 +3a026d8a +41ea4f8a +000da244 +a2442b0a +061a0020 +72ea088f +a2440917 +0c0a000d +0020a244 +088f060a +209772ea +08d70917 +a17c10e3 +7c001220 +001220a3 +0000a017 +a2840000 +341a0023 +1f8f108f +800a181f +5058ce65 +30a04400 +445b804a +80aa39a0 +00a06355 +ce300000 +0000a023 +08030a00 +1fcf108f +20a17c5f +58ce0012 +a0440050 +44324a30 +0aaa39a0 +0000a063 +12ea3000 +4a41a044 +46a04420 +a0631baa +37000000 +00a023ce +03100000 +cf108f08 +a17c4f1f +7c001220 +001220a3 +5f000082 +8233e208 +c6170000 +c46f0410 +b019ce00 +59ce0000 +570200b0 +40430006 +320dd708 +00008200 +00320092 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +c19704c0 +0cc1d710 +130a301f +085f3817 +96f02fce +08170010 +362301d7 +5f381714 +14c09708 +92f02fce +0392000c +f0820c32 +10c19710 +1714c117 +7c000c86 +0e0a301f +ce18c017 +1096f027 +18061700 +577cc027 +5731d701 +700e1720 +a1c713ea +1f000000 +800205ba +3b4b4e5e +c7388f00 +6cba70c1 +7c18c603 +0c7cc417 +320f9200 +08b08210 +001090df +000c915f +21ea38df +178f3897 +1092f017 +a0174e00 +97079701 +01170010 +01a1174e +0c972797 +c7388f00 +000000a1 +925bba1f +8200320d +01220400 +00320092 +0222b9df +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +00920000 +00000032 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b85f0880 +e710c5d7 +22000c85 +1f01d701 +17077a00 +000c08d4 +08320192 +07040082 +000c08d4 +85d7100a +0222000c +177c0617 +000c08d4 +08320092 +92000082 +00003200 +af14f082 +c19770c4 +34a57c0c +906724af +20970004 +0ba018ce +1700030e +078f10c0 +0000a007 +0b5a3200 +8f10c017 +ea015707 +a158ce06 +17385f32 +6c061728 +a1c71bea +32000000 +840205ba +103e0757 +8402055a +27e7144f +c7388f37 +64ba6cc1 +9270c4ef +8208320f +00df0800 +e20cc057 +9a005f00 +00374e05 +927c0617 +82043200 +c5d70400 +0cd07f0c +04320092 +ce040082 +7f0da5d8 +d8ce0cd0 +d07f0aa5 +9200220c +82003200 +d8ce0480 +3d040cc1 +c419aa30 +14aa39a1 +ce3818ce +2330a058 +7a001f08 +e4830205 +3d0426ea +c41faa41 +1aaa46a1 +ce3818ce +2341a058 +00a00308 +1f0a0000 +02057a00 +04eac283 +019207df +c0820812 +c198ce04 +c1d8ce0c +35d8ce10 +0208c5d7 +001fa4bf +d8ce0f6a +08c5d73d +1f97bf02 +ce177a00 +7f2aa5d8 +d8ce0cd0 +0cd07f35 +7f3dd8ce +23ea0cd0 +d735d8ce +bf0208c5 +a0174e75 +7c061704 +d73dd8ce +bf0208c5 +7cc00365 +d07f05d7 +1203920c +18f0820c +5f0cc157 +10c01720 +2007078f +2607134a +02055a10 +e01c3e83 +8f060a2c +5f68ea20 +5a21c738 +3e070481 +02055a10 +98ce2683 +a1842fe1 +e7801a2a +3e07388f +02055a10 +98ce1283 +18ce2fe1 +00a00730 +0a220000 +a0076980 +27000000 +076a800a +000000a0 +07270a4e +000000a0 +45800a50 +0000a007 +270a5300 +0000a007 +290a5400 +0000a007 +800a5800 +8880ea4a +0aa5d8ce +ce0cd07f +7f0da5d8 +80ea0cd0 +a5d8ce84 +0cd07f20 +df7a80ea +0495e7b9 +ea01222c +d8ce6f80 +d07f0ca5 +6580ea0c +27a5d8ce +ea0cd07f +d8ce5b80 +d07f22a5 +5180ea0c +090f3857 +335a2047 +108f3897 +5a101607 +74820205 +702ae614 +190f38d7 +5a101e07 +64820205 +6c2be614 +6cc5d8ce +70c5d8ce +be02bc2f +ea390fa0 +05d8ce08 +ea0cd07f +a5d8ce0f +0cd07f2a +7f35d8ce +08ea0cd0 +7f35d8ce +388f0cd0 +22fdbeea +320f9200 +08008208 +085f035f +00e210df +059a005f +1700374e +00927c06 +80820032 +0cc1d704 +00003d07 +1caa2000 +0000a1c7 +14aa7e00 +27a5d8ce +3dd70222 +d8ce0222 +022227a5 +d8ce14ea +02225ba5 +3dd7b95f +d8ce0322 +02225da5 +04320192 +07040082 +1a0c08d6 +e7b9df0c +22300495 +ce0bea01 +d708a5d8 +03220cc5 +04320092 +070cc082 +1a0c08d6 +e7b9df0d +22340495 +3e80ea01 +22a5d8ce +970cd07f +385f0cc1 +9800a1c7 +05ba8096 +1c858102 +0a0077e0 +00a1c719 +ba809698 +74810205 +77e5d8ce +0cd07f00 +5aea388f +22a5d8ce +920cd07f +82043203 +c11708f0 +14c1d710 +18c158ce +870cc197 +ce1c4a21 +38172dd8 +05d7078f +301725d7 +2fce085f +d7081720 +ea042205 +da389f10 +2dd8ce0c +8f0cd07f +1774ea3f +ce085f30 +0197202f +0000a007 +0f5a0a00 +30a018ce +05d73003 +ea0cd07f +a018ce13 +23300341 +000000a0 +7f05d70a +0f920cd0 +00821032 +a5d8ce04 +10c5d730 +10a5d8ce +220cc5d7 +32009204 +08808208 +1f0cc1d7 +107a0cc0 +1f39e34e +ce09da38 +7f2da5d8 +d8ce0cd0 +c5d720a5 +a5d8ce10 +223dd70a +32019204 +04008208 +20a5d8ce +d8ceb85f +c5d710a5 +9204220c +82043200 +b85f0400 +220cc5d7 +32009205 +04008204 +20a5d8ce +d8ceb85f +c5d70aa5 +9204220c +82043200 +00df0400 +1a0c0607 +e7badf0c +22380495 +5f1cea01 +0c060700 +badf0c1a +3e0495e7 +0bea0122 +95e7badf +22448004 +32009201 +04008204 +0010c507 +ba200000 +10c63717 +d7119a0c +c5d718c5 +ce012214 +7f20a5d8 +00920cd0 +00821032 +0cc69704 +3200920c +04008204 +0006b6a7 +3200920c +eab85f00 +22b9df04 +00000007 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b8df0000 +2c0495e7 +ce0cc5d7 +220da5d8 +32009201 +00008204 +95e7b8df +c5d72d04 +a5d8ce0c +9201220e +82043200 +d6070000 +170a0c08 +d5d7badf +e7badf18 +22000c85 +0a001f02 +ea00df06 +92005f04 +82043200 +c11700f0 +10c1970c +00148157 +0a08d187 +d731d71a +047dd725 +001f0322 +3157080a +09ea00df +ea007197 +17005f65 +9200142c +820c320f +c15704e0 +1c819718 +0cc5d700 +001f0422 +b85f091a +80ea0522 +14c5d746 +2210c5d7 +0c819706 +08d18708 +31d7300a +d7047dd7 +c5d714c5 +1f072210 +071a0a00 +00000c7d +0bba2000 +9a0c7977 +ea005f06 +22b8df11 +970bea05 +4fea0071 +0522ba5f +001c3417 +14320792 +d708c082 +c5e718c1 +1cc5d77c +d714c5d7 +c5d710c5 +9708220c +1a001f01 +381f3780 +b9df081a +2eea0522 +087c81c7 +b95f08ba +22ea0522 +147c8057 +178f3897 +0000a087 +05baff00 +67c79502 +ce004af0 +20004c03 +30170300 +18320392 +5708f082 +c1970cc1 +18811710 +222dd700 +14c05709 +08070f8f +d8ce0bba +0a2223a5 +5f5080ea +14c01738 +0617078f +c733ea78 +040000a1 +0205ba00 +3e077c95 +02055a14 +e7147495 +c700376f +040000a1 +0205ba00 +e01c6495 +081a006f +005f3917 +388f14ea +ba78c1c7 +14c0174c +008f078f +005f0117 +00182417 +10320f92 +07040082 +000c08d4 +85e70d0a +0b22000c +0c08d417 +32009200 +04008204 +1a1cd01f +ea00df06 +92005f04 +82003200 +0c220400 +1d0a001f +0000a687 +1a3c0d00 +0cc5d70c +06970522 +d70aea1c +0a220cc5 +921c0697 +82043200 +c01f0400 +220c7a0c +0a001f0c +0cc69706 +3200921c +04008204 +000c8027 +d7280697 +c5d710c5 +970d220c +d05f2c06 +32009220 +04008208 +2420d697 +202cd687 +d0171e5a +00a00720 +baff0000 +9e940205 +2890e414 +8f000c00 +00df20d0 +a41409ea +5f000c00 +32009200 +04008204 +202cd687 +d0171b5a +00a00720 +baff0000 +6e940205 +2890e414 +df000c00 +1409ea00 +000c00a4 +0092005f +00820432 +38d01f04 +d05f0f0a +24d01738 +0697078f +9706ea20 +922024d6 +82003200 +85e70400 +0e22000c +0c0a001f +000c85e7 +00df0f22 +005f04ea +04320092 +5f040082 +85e738d0 +0e22000c +260a001f +0c7ca404 +e71d1a00 +22000c85 +0a001f0e +38d0df09 +14ea00df +11a5d8ce +005f1022 +06ea0aea +04ea005f +009200df +00820432 +78c4af0c +8f14c017 +57057f00 +14af10c0 +af00000e +d8ce10c4 +d5d70ba5 +14c5d730 +2210c5d7 +7cc5e711 +001f0e22 +043d800a +0a7c22a6 +27a60408 +94111a7c +00307cc4 +3000a494 +34d0df01 +a60421ea +161a7c3c +1a0cc01f +9483ce11 +00302e04 +5f122203 +07ea34d0 +d05f1322 +78c4ef34 +0c320092 +e7080082 +0e227cc5 +0a0a001f +7c20a604 +71ea041a +00921322 +00820032 +38d01f04 +d8ce141a +ce000c85 +d70ba5d8 +142230d5 +061a001f +04ea00df +0092005f +00820432 +78c4af0c +8f10c017 +57057f00 +14af0cc0 +af00000e +c05f0cc4 +7cc5e77c +14c5d8ce +d710c5d7 +15220cc5 +9278c4ef +820c3200 +c5d70880 +00c81f10 +9202057a +0c85e7fd +d7162200 +7a001f01 +08d4170a +0697000c +3201921c +08808208 +0c08d407 +d7160a00 +22000c85 +1f01d717 +97057a00 +d4171c06 +92000c08 +82043201 +c4af1480 +01a57d70 +78c4af00 +c5e7385f +1f182274 +e72e0a00 +192274c5 +250a001f +0000a1c7 +05baff00 +148b9202 +787487c7 +00a1c700 +5aff0000 +ea388f06 +22bbdf06 +224dea10 +34d01f13 +c5e7220a +1f0e2274 +ce130a00 +ce74c5d8 +d70ba5d8 +142230d5 +081a001f +13a5d8ce +0c221022 +340a001f +1a34d01f +0a381f06 +00a1c72b +aaff0000 +00a1c713 +baff0000 +2a920205 +0087a714 +d9ce0078 +d70001a5 +1a2278c5 +000c0417 +d41707ea +22000c08 +0a001f0c +08d4070d +060a000c +04ea00df +c4ef005f +32019270 +04808204 +0ca5d8ce +000c85e7 +0c221b22 +110a001f +000c81d7 +1893c3ce +d7070000 +220808d3 +3201920c +08008204 +95e7ba5f +b8df3104 +85e71c22 +1d22040c +0f0a001f +04a5d9ce +0c85d701 +ea062204 +22bb5f06 +920c2210 +82043200 +c4af18c0 +14c1976c +af08a57c +c05f70c4 +9403ce7c +00703604 +7cc5e707 +0cc5d8ce +c5d7bbdf +1f152270 +17130a00 +039f7cc0 +910205ba +10041775 +bb80ea00 +0c3fa604 +df10801a +ce001083 +1027a399 +a780ea24 +0cc5d8ce +0aa5d8ce +3e0495e7 +001f1422 +df8e800a +04001083 +1a0c3da6 +2870df14 +220cc5e7 +1a001f0e +a5d8ce08 +2210220a +1871e713 +95e7ba5f +df498004 +e71c22b8 +1d2278c5 +130a001f +04a5d9ce +78c5d701 +2274c5e7 +2205d71e +00a6071f +74102700 +d8ce0bba +10220ba5 +d70c78df +220c74c3 +74c01f13 +d8ce081a +10220ca5 +1a0c711f +24709f0d +d8ce080a +10220da5 +1a0c719f +24709f0d +d8ce080a +10220ea5 +d8ce08ea +102208a5 +c4ef0c22 +1203926c +18e08210 +6c08d617 +0c22305f +800a001f +7cc5e765 +001f0e22 +045b800a +1a7c2fa6 +c5e75480 +1f20227c +d7360a00 +c5e70cc5 +c5d8ce78 +02bc2f7c +001fccbe +c5072c0a +00000078 +b70fba20 +0a9a78c1 +0fa5d8ce +16ea1022 +0000a607 +ba781f00 +ea04ea09 +4a90020b +78c19b4e +d8ce08ea +102208a5 +229abfea +2b301713 +000000a0 +d701577c +a1b40cc1 +df069a00 +5f04ea08 +180bd708 +9a01a1b4 +ea10df06 +d7105f04 +05d72013 +00d72122 +0bba189f +09a5d8ce +80ea1022 +02a1747b +5f27809a +78df0c79 +24789f20 +d8ce080a +10220da5 +df2478df +b85f0878 +d76cc5e7 +22220cc5 +745180ea +809a03a1 +0c78df09 +744580ea +809a04a1 +0c785f09 +743980ea +809a05a1 +0c7adf2b +227cc5e7 +0a001f23 +2da6041c +5f161a7c +0495e7ba +b8df4e80 +7de71c22 +1f1d221c +ea020a00 +06a1740a +79df059a +920c220c +82043207 +c4af10c0 +04a57c74 +c1d734af +08d4070c +0a1a0010 +0a0c791f +a780ea05 +9f0c7817 +0205ba02 +ef7d508f +003704d8 +00100023 +00780078 +d407004b +0a001008 +ea08df06 +97085f04 +80ea000b +a5d9ce64 +85d70104 +35d70010 +05d72422 +80ea1f22 +a5d9ce50 +85d70104 +35d70010 +05d71e22 +80ea1f22 +a5d8ce3c +a5d9ce2d +85d70104 +14220010 +090a001f +00108397 +d70eea00 +85d71c7d +25220010 +17000397 +001008d4 +83970eea +17000010 +001008d4 +85e702ea +26220010 +001f0c22 +35d70c0a +d714c5d7 +27220cc5 +9274c4ef +820c3203 +c19704c0 +0cc1d710 +4a087987 +8f301709 +0803d700 +08247bc7 +d8ce0aba +102217a5 +79872bea +d7074a10 +28220cc5 +001f0c22 +78171b0a +00a18714 +baff0000 +6a8e0205 +0046f027 +148203ce +92030000 +820c3203 +81e710e0 +781f100c +df061a00 +1709ea28 +020f0078 +28170157 +02a0174e +c5e705d7 +221b227c +0a001f0c +305f5d80 +1a5a2987 +0000a187 +05baff00 +271f8e02 +007c86f0 +0008d217 +66ea308f +7987305f +172b5a00 +a1870478 +ff000000 +8d0205ba +46f027fd +00a18700 +baff0000 +ee8d0205 +864783ce +03007c00 +54ea308f +22047de7 +7cc3d729 +002bd704 +04320792 +d708c082 +7d070cc1 +0000000c +ce2cba20 +3738a018 +239a0c78 +7987305f +171c5a10 +a1871478 +ff000000 +8d0205ba +46f027a5 +2205d700 +ea308f26 +147de763 +785f2922 +32039210 +18808204 +7c6cc4af +c4af04a5 +7cc5e774 +001f0e22 +0489800a +1a7c5ba6 +811f8280 +0d1a0c0c +14a5d8ce +005f1022 +9f7580ea +1a0c0c81 +a5d8ce0d +5f102215 +6480ea00 +280c801f +d8ce0d0a +102216a5 +80ea005f +22385f53 +e7b9df12 +53800495 +1c22b8df +2278c5e7 +0a001f1d +e73dd70c +c5d778c5 +8f22220c +78c5e738 +0c222622 +110a001f +227cc5e7 +0a001f0e +5da60408 +04461a7c +0a7c5da6 +a5d8ce08 +ea102210 +22132204 +6cc4ef0c +04320192 +07040082 +000c08d4 +84170a1a +000c7c08 +80170eea +05d7000c +0208c5d7 +0092e5bf +00820812 +a5d8ce08 +7cc5e730 +0c221b22 +180a001f +9710c057 +18ce7cc0 +030e0ca0 +0c85e700 +02bc2f08 +0092b9bf +00820832 +74c4af10 +af30a57c +98ce7cc4 +d73c0da6 +17140885 +d7100880 +222a2205 +08d41712 +d417007c +5f047c08 +5f087c80 +5f0c7c82 +17107c80 +147c08d4 +187c805f +7c08d417 +7c805f1c +7c80df20 +7c805f24 +7c805f28 +7cc5d72c +001f2b22 +c5d7240a +1f2c227c +d71b0a00 +2d227cc5 +0d0a001f +d77cc5d7 +227c0885 +d707ea2e +2f227cc5 +2278c5e7 +0a001f0e +c5d8ce17 +e7b95f78 +57800495 +001f1422 +badf061a +c5e71022 +1f0e2278 +ce150a00 +5f78c5d8 +0495e7b9 +14225a80 +040a001f +132266ea +0a78c01c +1f0c2209 +5cbf1a00 +c4ef0c22 +12009274 +0c808204 +7c0885e7 +12222622 +5720d1d7 +485708c0 +6c4de708 +001f0e22 +c057380a +08485708 +6c2da244 +c0972c1a +08509708 +226c55e7 +0a001f23 +08c0571d +ce084857 +ce6c4dd8 +e70aa5d8 +5d800495 +001f1422 +04ea041a +b95f1322 +800495e7 +22b8df68 +0885e71c +1f1d227c +ea041a00 +a5d9ce2e +85d70104 +06227c08 +577cc5e7 +485708c0 +08485708 +d77c4817 +85d70845 +30227c08 +040a001f +bfea05ea +08c0576e +e7084857 +2622784d +c0573dd7 +08485708 +ce7c4dd7 +0001a5d9 +2228d5d7 +08c05731 +57084857 +00df7802 +04120192 +d7080082 +22780885 +7c061732 +1a08d007 +ea005f07 +d9ceb480 +d70104a5 +06227cc5 +740885e7 +5708c057 +48170848 +0845d77c +227cc5d7 +0a001f30 +d4177080 +177c0820 +17740880 +019f0c40 +bc2f0a1a +eaedbe02 +85e77880 +23226c08 +130a001f +082ca404 +e70c1a6c +26227cc5 +80ea005f +0880175d +0c401774 +041a011f +85e725ea +26227808 +b95f1222 +800495e7 +22b8df6b +0885e71c +1f1d2278 +ce081a00 +2219a5d8 +7cc5e710 +00df2622 +072380ea +740808d4 +8017140a +40177408 +1a019f0c +02bc2f09 +09ea7ebe +227cc5e7 +92005f26 +82041200 +81d70480 +d1c7000c +1f0c0a08 +070a2078 +ea0079d7 +0c3c1773 +12019200 +04c08208 +870cc197 +800a08d1 +1f31d72b +0d0a1878 +5a08789f +a5d8ce08 +1f10221a +0e0a2878 +08247bc7 +d8ce085a +10221ba5 +ea007197 +12039254 +1c008208 +7c68c4af +c4af04a5 +a698ce70 +85d73c0e +80171c08 +05d71808 +80172a22 +46177c08 +c5e77408 +1f23226c +1c020a00 +800a6cc0 +74c5e7e0 +bf02bc2f +20d61771 +e712227c +0e226cc5 +800a001f +2da6044d +46801a6c +226cc5e7 +0a001f23 +d8ce3c80 +d8ce6cc5 +95e70aa5 +226e8004 +1a001f14 +b95f2880 +800495e7 +22b8df79 +78c5e71c +001f1d22 +bc2f0b0a +1f58be02 +ce081a00 +221ea5d8 +2221ea10 +e7b95f13 +7c800495 +1c22b8df +2278c5e7 +0a001f1d +02bc2f0b +001f31be +d607020a +0d1a7408 +18a5d8ce +005f1022 +225c80ea +0a001f0c +7485d712 +78c5e72c +2274c5d7 +74808f22 +78c5e72c +12222622 +226cc5e7 +0a001f0e +2ca6040a +ea041a6c +74861711 +c5e77400 +02bc2f74 +1322acbe +c5e71222 +1f23226c +ea020a00 +801720bf +45d77c08 +02bc2f08 +0c22aebe +9268c4ef +82041200 +d9ce0400 +d70104a5 +227c0885 +0885e706 +08c09778 +57085097 +4dd77c50 +0885d708 +9230227c +82041200 +d1d71480 +1cd05f1c +1c0885d7 +18088017 +2a2205d7 +c5e71222 +1f0e2274 +040a0a00 +0a742da6 +5f132204 +0495e7b9 +b8df7f80 +c5e71c22 +1f1d227c +58800a00 +bf02bc2f +0a001f99 +85d74980 +ba5f0478 +800495e7 +1f332282 +ce130a00 +221fa5d8 +1c06970a +227cc5e7 +4c80ea26 +047885d7 +08a5d8ce +800495e7 +1f332287 +ce130a00 +2220a5d8 +1c06970a +227cc5e7 +2880ea26 +227cc5e7 +e7122226 +0e2274c5 +0c0a001f +742ca604 +1222061a +132204ea +1a74c01c +3e9769bf +1201921c +0c008204 +ce1cd05f +3c0da698 +227cc5e7 +0a001f34 +02bc2f22 +001f2fbb +bc2f190a +1fddbd02 +170b0a00 +000c7cc4 +12ea005f +bf02bc2f +7cc5d719 +06173522 +1cd01778 +14320092 +d7080082 +04220cc5 +800a001f +08d4073a +800a080c +0c861720 +85e77c08 +2622047c +227cc5d7 +7c84172f +e7080c00 +29227cc5 +03ce5dea +90800494 +e707000c +29220cc5 +06ea005f +0522b85f +04320092 +020c0082 +00925087 +c0820432 +17385f14 +c7000c80 +040000a1 +0205ba00 +18ce3087 +040047e0 +061a20a0 +65ea388f +000c8017 +0000a1c7 +05ba0004 +ce138702 +0047e018 +1a2da004 +df388f0a +ea5c0880 +08805f06 +783e175c +ce78c5e7 +d720a5d8 +22000c85 +1a001f36 +0a381f06 +78c5d719 +85d73dd7 +3722000c +85e70197 +2622000c +000c3417 +08120392 +d7108082 +d7700885 +d7740885 +571c0885 +d7180880 +1731220d +05d77c06 +001485d7 +06172522 +7cc5e778 +c5d72622 +10c5d778 +220cc5d7 +e701d738 +262278c5 +001485e7 +3c172622 +01920014 +f0821012 +70c4af14 +7c0cc117 +34af04a5 +781f21d7 +17231a08 +146c0880 +e70000a2 +ce640885 +0001a5d9 +c5d705d7 +8bbf0208 +0820d417 +7481ea74 +781728df +6c061708 +176381ea +28571478 +a0470f8f +ff000000 +860205ba +41f0272d +4183ce00 +78970300 +ba129f0c +1e860205 +04daef7d +00800066 +0010009a +00230010 +01a5d9ce +0880d700 +d71dd76c +39220075 +1f9f80ea +0a5c0880 +78c05f2c +ce78c5e7 +d72da5d8 +36220075 +020a001f +01a5d9ce +08801700 +d705d76c +b85f78c5 +220075d7 +ce12ea3a +0001a5d9 +6c0880d7 +75d71dd7 +ea392200 +d8ce5c80 +75d710a5 +a5d9ce00 +80d70001 +1dd76c08 +04173b22 +39ea6808 +10a5d8ce +ce0075d7 +0001a5d9 +6c0880d7 +3c221dd7 +68080417 +701f27ea +ce140a00 +0001a5d9 +6c0880d7 +65d71dd7 +ea392204 +0880d70e +ea04ea6c +00a2d408 +ce02ea00 +0001a5d9 +6c088057 +0d220dd7 +68080417 +5a087947 +00a00736 +aaff0000 +0880173a +0880576c +00a04768 +baff0000 +2a850205 +2c41a714 +08808f00 +00a40768 +08ff0000 +571eaa68 +ea680880 +4716ea04 +000000a0 +ea09baff +020aea04 +a7140085 +e7000041 +ce640885 +0001a5d9 +6c088017 +c5d705d7 +1fbe0208 +0820d417 +47288f74 +beba6cc1 +70c4ef9d +08120f92 +af308082 +c01754c4 +7f008f1c +18c05705 +000e14af +18c4af00 +7d20c1d7 +af0001a5 +d6176cc4 +c05f6408 +1cd05f74 +d71cc5d7 +2a2218c5 +6c00a414 +17122200 +df7020d6 +0495e7b9 +b85f9680 +c5e71c22 +1f1d2260 +be800a00 +0ba5d8ce +5f30d5d7 +0495e7b9 +3d229a80 +800a001f +e71222a4 +0e2278c5 +080a001f +783ea604 +d8ce0e0a +0a2222a5 +ea1c0697 +c5e78780 +02bc2f60 +d9ce03bd +d70104a5 +062260c5 +ce7cc5e7 +ce3fa5d8 +0104a5d9 +d760c5d7 +1f08223d +1f206a00 +110a5cc0 +0c7c829f +d8ce0b0a +052224a5 +d71c0697 +bc2f7cc5 +ea8abd02 +5cc01f3b +d9ce2d1a +d70104a5 +c5e760c5 +a5d9ce68 +c5d70001 +1f3e226c +e7146a00 +d9ce64c5 +d70001a5 +bc2f6cc5 +ea10bd02 +a5d8ce0b +970a2221 +d6171c06 +c5e77420 +22262260 +78c5e712 +001f0e22 +d8ce150a +b95f78c5 +800495e7 +1f14229d +ea040a00 +1c132204 +bf1a78c0 +1f0c2202 +172d0a00 +147020d6 +006c00a4 +ce64c5e7 +0001a5d9 +2f6cc5d7 +b7bc02bc +001485e7 +d710c5d7 +c5d70cc5 +973f2264 +c5e71c06 +17262264 +c4ef1cd0 +32019254 +08008218 +177cc4af +008f14c0 +c057057f +0e14af10 +c4af0000 +1cc01710 +057f008f +af18c057 +00000e14 +d718c4af +c5d71cc5 +14c5d718 +e710c5d7 +22000c85 +c4ef4080 +3200927c +04008214 +220cc5d7 +00924180 +80820432 +74c4af10 +8f1cc017 +57057f00 +14af18c0 +af00000e +a57c18c4 +78c4af04 +ce78c5d7 +d738a5d8 +c5d720c5 +18c5d71c +2224c5d7 +01d74280 +141a001f +001485e7 +d710c5d7 +85d70cc5 +3f220078 +c4ef01d7 +32019274 +1080821c +1774c4af +008f14c0 +c057057f +0e14af10 +c4af0000 +04a57c10 +d778c4af +ba5f78c5 +c5d7b8df +10c5d714 +2218c5d7 +01d74280 +081a001f +00788417 +c4ef000c +32019274 +10808210 +1774c4af +008f14c0 +c057057f +0e14af10 +c4af0000 +04a57c10 +d778c4af +b95f78c5 +d718c5d7 +c5d714c5 +1cc5d710 +d7428022 +1a001f01 +78841708 +ef000c00 +019274c4 +80821432 +74c4af10 +8f14c017 +57057f00 +14af10c0 +af00000e +a57c10c4 +78c4af04 +df78c5d7 +18c5d7b8 +d714c5d7 +c5d710c5 +4280221c +001f01d7 +8417081a +000c0078 +9274c4ef +82143201 +c4af1080 +14c01774 +057f008f +af10c057 +00000e14 +e710c4af +d8ce78c5 +c5d73fa5 +10c5d714 +2218c5d7 +1f01d708 +17081a00 +0c087884 +74c4ef00 +10320192 +d7040082 +c5d720c5 +18c5d71c +001485e7 +d710c5d7 +80220cc5 +32009243 +04008218 +220cc5d7 +32009235 +10808204 +1774c4af +008f10c0 +c057057f +0e14af0c +c4af0000 +18c0170c +057f008f +af14c057 +00000e14 +d714c4af +c5d718c5 +10c5d714 +e70cc5d7 +802278c5 +1f01d740 +5f097a00 +2205d7ba +c0174480 +74c4ef78 +10320192 +d70c8082 +c5d720c5 +18c5d71c +e714c5d7 +c5d778c5 +0cc5d710 +d7458022 +7a001f01 +78c05f0c +05d7bb5f +17448022 +019278c0 +80821832 +14c5d70c +d710c5d7 +c5e70cc5 +46802278 +001f01d7 +b9df097a +802205d7 +78c01744 +0c320192 +d70c8082 +c5d718c5 +10c5d714 +e70cc5d7 +802278c5 +1f01d747 +5f097a00 +2205d7ba +c0174480 +32019278 +0c808210 +d718c5d7 +c5d714c5 +0cc5d710 +2278c5e7 +01d74880 +097a001f +05d7ba5f +17448022 +019278c0 +80821032 +14c5d70c +d710c5d7 +c5e70cc5 +49802278 +001f01d7 +b9df097a +802205d7 +78c01744 +0c320192 +d7088082 +c5d720c5 +18c5d71c +001485e7 +d710c5d7 +80220cc5 +1f01d743 +5f097a00 +2205d7bb +01924480 +80821832 +0cc5d708 +01d73522 +097a001f +05d7b8df +92448022 +82043201 +80220400 +0cd05f4a +5f10d05f +83ce14d0 +a0800494 +92070018 +5f003200 +df0ceab8 +5f08eab8 +df04eab9 +4b8022b9 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b8df0000 +2c0495e7 +df0cc5d7 +920122b8 +82043200 +c1d704c0 +c7381f0c +000000a1 +ce0daa09 +0330a018 +0198ce38 +18ce11ea +380361a0 +0000a023 +98ce0a00 +3018ce01 +04320392 +9700c082 +c1d70cc1 +4a398710 +173dd734 +ce085f30 +0817382f +022205d7 +185f3097 +d738afce +57032215 +a04710d0 +23000000 +840205ba +91071481 +d08f000c +d71cea10 +57032235 +a04710d0 +23000000 +840205ba +91071465 +d08f000c +32039210 +10f08208 +00188157 +98ce285f +c05f0aa1 +10c01778 +c007078f +ea055a14 +c017c281 +10060714 +8402055a +e118ce31 +ce000c80 +a0472058 +7a000000 +81ea05ba +d9ef7d5f +5c01a004 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +5c015c01 +fa00fa01 +fa00fa00 +fa00fa00 +fa00fa00 +fa00fa00 +5c015c00 +5c015c01 +5c015c01 +08015c01 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +08010801 +5c010801 +5c015c01 +30015c01 +1c015c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +1c011c01 +ce011c01 +d8ce2098 +18a330a0 +80ea11d7 +2098ce5d +41a0d8ce +a08318a3 +0a000000 +80ea11d7 +2098ce49 +61a0d8ce +a08318a3 +0a000000 +80ea11d7 +1f299735 +080a78c0 +0422b8df +c0df3dea +00350778 +aa020000 +00a1870a +ba240000 +22b85f08 +5f3cea04 +ea285f38 +22b8df08 +c73bea04 +5f084a31 +ea0422b9 +ffa01738 +23ffffff +ea085f38 +ce2aea04 +0817302f +085a2807 +0422b9df +28171bea +ea3027ce +0312ea04 +8f015738 +04ea14c0 +beea07ea +17005f37 +9200182c +8210320f +305f10e0 +360738df +02055a14 +18ce6482 +001086e0 +0000a007 +0c0a2b00 +0000a007 +080a2d00 +308f0cea +3fdf08ea +02ea308f +d770c5e7 +14c5d735 +2210c5d7 +1f015705 +ea057a00 +381f2c80 +d607087a +0faa7008 +11da381f +ff7fa607 +ba70ffff +22b9df08 +170eea04 +c023ce38 +0c041770 +92005f00 +820c3207 +385f08c0 +5a143e07 +f2810205 +87e018ce +a0070010 +2b000000 +a0070c0a +2d000000 +0cea080a +08ea388f +0422b8df +85e712ea +3dd7000c +d714c5d7 +052210c5 +03920197 +c0820c32 +18c19700 +5f1cc1d7 +3d0710d0 +02000000 +a1c70aaa +24000000 +b85f09ba +80ea0422 +7a301f80 +31a34e1c +0710d017 +000000a0 +0205ba23 +a7148481 +000c2d90 +c710d08f +000000a1 +ce210a0a +d70aa5d8 +1702223d +a00710d0 +23000000 +810205ba +90a7145d +8f000c5f +3dd710d0 +c81f35d7 +02057a00 +02224c81 +0710d017 +000000a0 +0205ba23 +a7143881 +000c0090 +d710c5d7 +d8ce0cc5 +d5d724a5 +1706220c +001410d4 +0392005f +80821432 +1cc1d700 +0710d05f +0000003d +c70aaa02 +000000a1 +5f09ba24 +ea0422b8 +a1c75b80 +0a000000 +d8ce210a +3dd70aa5 +d0170222 +00a00710 +ba230000 +da800205 +5f90a714 +d08f000c +d73dd710 +022218c5 +0710d017 +000000a0 +0205ba23 +a714bc80 +000c0090 +d710c5d7 +d8ce0cc5 +d5d724a5 +1706220c +001410d4 +0192005f +80821432 +10c5d708 +e70cc5d7 +072278c5 +001f01d7 +b95f087a +082205d7 +9278c017 +82083201 +c5d70880 +0cc5d710 +2278c5e7 +1f01d709 +5f087a00 +2205d7b9 +78c01708 +08320192 +d7088082 +c5d718c5 +78c5e714 +d710c5d7 +0a220cc5 +001f01d7 +ba5f087a +082205d7 +9278c017 +82103201 +c5d70880 +14c5d718 +d778c5e7 +c5d710c5 +d70b220c +7a001f01 +d7ba5f08 +17082205 +019278c0 +00821032 +920c2200 +5f003200 +df04eab8 +000d22b9 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b8df0000 +2c0495e7 +ce0cc5d7 +2209a5d8 +32009201 +0cc08204 +1774c4af +008f10c0 +c057057f +0e14af0c +c4af0000 +08a57c0c +83ce34af +072d0491 +d710c5d7 +02220cc5 +d710c5d7 +03220cc5 +065a019f +2cea005f +22ea385f +05ba3a1f +cee28602 +0737e018 +055a103e +04d68602 +000c8707 +005f060a +388f0aea +5eba399f +c4ef00df +32039274 +00808208 +0cc1d8ce +073818ce +000000a0 +070a4a41 +000000a0 +ea05ba7a +a0238f80 +41000000 +04d8ef7d +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00860086 +00860086 +00860086 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +00780078 +2b3818ce +000000a0 +01d8ce5f +18ce02ea +12019238 +1cf08208 +3c17385f +285f0014 +5a10d1c7 +281f9d80 +df98801a +143c1728 +00a1c700 +baff0300 +e5850205 +97e018ce +0117000c +0617388f +10c5d76c +220cc5d7 +47005703 +801a6cc0 +17305f4c +17078f20 +39ea6806 +0000a1c7 +05baff03 +ceb28502 +0c97e5d8 +02bc2f00 +0614eebe +10360764 +8502055a +e5d8ce9c +2f000c86 +d8be02bc +0a64c004 +8f285f04 +87308f38 +46ba68c1 +21c306ea +a1c7285f +ff030000 +850205ba +e018ce70 +03000c97 +d7008f38 +63bfea01 +0f922817 +f0820c32 +0cc1971c +0000a187 +05baff03 +ce4a8502 +0c96e018 +57008f00 +57300301 +00a04700 +baff0300 +31850205 +91e058ce +0e17000c +1728437c +57008f08 +10d05701 +00633063 +385f0917 +16172097 +172cea6c +03280330 +00a00738 +baff0300 +fd840205 +38433057 +0000a047 +05baff03 +14ee8402 +0c9190e7 +8f000c00 +6cc1c738 +2ea353ba +320f9210 +1cf08204 +d710c5d7 +03220cc5 +c5d70197 +14c5d718 +01570322 +00573003 +0917090f +0000a147 +0aaaff00 +0000a187 +07baff00 +80ea005f +a019ceac +d0230004 +5a080710 +ea005f07 +30179b80 +8710d097 +030000a0 +0205baff +07148384 +8f000c92 +385f10d0 +078f3017 +ea6c0617 +103e0725 +8402055a +10d01768 +0000a007 +05baff03 +145a8402 +0c9087e7 +8f000c00 +388f10d0 +ba6cc1c7 +5728175a +a04710d0 +ff030000 +840205ba +91071438 +d08f000c +17385f10 +17078f28 +25ea6c06 +5a183e07 +1d840205 +0710d017 +030000a0 +0205baff +e7140f84 +00149087 +d08f000c +c7388f10 +5aba6cc1 +0f9200df +f0821032 +0cc11710 +00148157 +8718c197 +030000a1 +0205baff +18cedf83 +000c96e0 +008f0157 +c0170057 +47078f10 +5f06ba00 +8f3bea00 +17385f30 +17078f28 +1fea7806 +0000a187 +05baff03 +07ae8302 +055a103e +14a68302 +0c2796e7 +8f308f00 +78c1c738 +2e0760ba +02055a10 +04ea8f83 +a71408ea +00df0025 +00142c17 +10320f92 +af140082 +c01778c4 +7f008f10 +0cc05705 +000e14af +0cc4af00 +d710c5d7 +02220cc5 +d710c5d7 +d8ce0cc5 +95e708a5 +04223204 +290a001f +001c85e7 +d718c5d7 +052214c5 +147a001f +d718c5d7 +bbdf14c5 +3b0495e7 +83df0022 +00df001c +d76f80ea +c5d710c5 +a5d8ce0c +0495e708 +04224380 +800a001f +1c85e72a +18c5d700 +2214c5d7 +7a001f06 +18c5d715 +df14c5d7 +0495e7bb +00224c80 +001c83df +31ea00df +d710c5d7 +d8ce0cc5 +95e70ba5 +22548004 +0a001f04 +18c5d71a +2214c5d7 +18c5d707 +2214c5d7 +1c041703 +ea00df00 +ef005f04 +009278c4 +80821812 +70c4af1c +8f1cc017 +57057f00 +14af18c0 +af00000e +85e718c4 +c5d70014 +0cc5d710 +d71cc5d7 +bc2f18c5 +1f08bf02 +5f060a00 +e73cea00 +c5d778c5 +18c5d71c +001f0822 +5741800a +a04778c0 +ff030000 +820205ba +e018ce5c +03000c91 +008f78c0 +d7780617 +1485e705 +10c5d700 +ea0cc5d7 +2226ea04 +0a001f09 +ea385f06 +22b85f08 +ea01d70a +1cc5d712 +df18c5d7 +d70a22b8 +d70b2205 +ef381701 +019270c4 +00821432 +78c4af14 +8f10c017 +57057f00 +14af0cc0 +af00000e +c0170cc4 +7f008f18 +14c05705 +000e14af +14c4af00 +d710c5d7 +0c220cc5 +120a001f +d710c5d7 +b95f0cc5 +05d70a22 +3aea0b22 +d77cc5e7 +c5d710c5 +1f08220c +d7070a00 +0d227cc5 +d718c5d7 +032214c5 +061a001f +20ea005f +d718c5d7 +c5d714c5 +0cc5d710 +001f0e22 +04ea0a0a +005f0aea +b9df06ea +c4ef0a22 +32009278 +18008210 +7c74c4af +c4af0ca5 +0cc0177c +0e0a001f +250a009f +800a011f +5480ea3c +d714c5d7 +d8ce10c5 +95e708a5 +22608004 +a418ce00 +5f001808 +d73cea00 +c5d714c5 +a5d8ce10 +0495e708 +00226980 +08a418ce +005f0018 +c5d730ea +10c5d714 +0ba5d8ce +800495e7 +ce002272 +180ba418 +ea005f00 +eab8df15 +e70fea04 +7e800495 +0a22b8df +0b2205d7 +9274c4ef +82141200 +c19714e0 +1f385f18 +3b800a30 +5a10d1c7 +a1c73580 +ff030000 +800205ba +e018cedc +03000c97 +d7008f38 +00a00701 +baff0300 +c5800205 +90e058ce +0043000c +09d7088f +45ea378f +4a10d1c7 +1485e717 +10c5d700 +d70cc5d7 +02bc2f35 +01571ebf +3dd71eea +001485e7 +d710c5d7 +09220cc5 +060a001f +08ea285f +0a22b85f +28170157 +10320792 +d7148082 +c5d718c5 +78c5e714 +d710c5d7 +0f220cc5 +001f01d7 +ba5f087a +102205d7 +9278c017 +82103201 +c5d71080 +14c5d718 +d710c5d7 +11220cc5 +001f01d7 +ba5f087a +102205d7 +10320192 +d7108082 +85e718c5 +c5d70014 +0cc5d710 +01d71222 +087a001f +05d7ba5f +01921022 +00821032 +5f13220c +009210d0 +b85f0032 +00001422 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +d1d70480 +08d1c738 +3dd70b0a +79d70122 +9274ea00 +82003201 +c19700c0 +08d1870c +b9df0d1a +2c0495e7 +80ea0222 +5f31d788 +2235d7bb +e7b95f03 +22300495 +e7badf02 +22330495 +d7bb5f02 +0322047d +08a5d8ce +390495e7 +bb5f0222 +22087dd7 +107dd703 +001f0422 +badf0d0a +800495e7 +ea022242 +e7badf0b +48800495 +b9df0222 +800495e7 +5f02224e +0c7dd7ba +b9df0322 +800495e7 +5f022252 +107dd7b9 +05d70522 +b9df0322 +800495e7 +5f022256 +107dd7b9 +05d70622 +07220322 +04320392 +df000082 +0495e7b8 +c5d75a80 +22b95f0c +32009208 +10c08204 +d774c4af +a57c10c1 +78c4af18 +0a18d01f +22b85f09 +a980ea09 +091a381f +0922bb5f +1f9e80ea +5f23da38 +2cd5d7b8 +4730d5d7 +ff0000a6 +05ba00ff +d7e28d02 +0c85e73d +970a2200 +7780ea01 +d739e34e +0b2278c5 +81c70197 +06da0c78 +0c7881d7 +d5d7b85f +30d5d72c +0000a647 +ba00ffff +ad8d0205 +85e73dd7 +0a22000c +06170197 +22badf70 +47005709 +801a70c0 +003d0736 +da000100 +22b8df09 +2980ea09 +0000a1e3 +b85f0001 +d72cd5d7 +a64730d5 +ffff0000 +0205ba00 +3dd76b8d +000c85e7 +01970a22 +c4ef3017 +32039274 +04008208 +b85fb85f +c5d7b85f +0c85e710 +920a2200 +82083200 +b8df0400 +b85fb85f +e710c5d7 +22000c85 +3200920a +08808208 +0a18d01f +22b85f08 +d70bea09 +c69730d1 +3817300c +04320192 +170cc082 +2b000c80 +000000a0 +d7019703 +1f000c81 +5f080a00 +c300630a +0c3c1709 +12039200 +04008208 +000c8017 +fea0174e +02a0174e +000c0417 +08120092 +e70ce082 +bc2f0cc5 +e7bcbf02 +bc2f14c5 +e7b4bf02 +bc2f10c5 +e7d1bf02 +bc2f18c5 +07c9bf02 +5a0c10c6 +14c6071c +07165a10 +5a1418c6 +14c01710 +0000a003 +c007e803 +ce0d4a18 +e71ba5d8 +5b800495 +c0170c22 +00a00314 +97e80300 +c0571006 +97006318 +c697140e +d0df2010 +2cd05f34 +3c08d697 +a187305f +32000000 +a1871dca +32000000 +8c0205ba +96f82748 +5f004080 +405f0040 +ea308f04 +14c4975f +5f044080 +a5d9ceb8 +c5d7e803 +570d2214 +7a001f01 +a5d8ce0d +0495e718 +0c227780 +06970e22 +38d1d738 +0008d3d7 +040cc3d7 +6318c057 +0bd70cc0 +e7b85f08 +0f22107d +5f0c785f +107de7b8 +d05f1022 +10c5d718 +220cc5d7 +6a001f11 +14c5d72d +2210c5d7 +6a001f11 +10d5d721 +2214c5d7 +6a001f11 +0cc5d715 +001f1222 +d5d70c6a +1f122210 +0e807a00 +1ea5d8ce +800495e7 +df0c2290 +d5e724d0 +a5d8ce0c +0495e70e +badfb580 +800495e7 +5f1322af +32079200 +04008210 +0a18d01f +22b85f08 +8f07ea09 +005f2cd0 +00320092 +1f040082 +080a18d0 +0922b85f +d5d70eea +2214222c +2cd78f15 +0092005f +00820032 +18d01f04 +b85f080a +1fea0922 +d5d7b85f +14c5d72c +0000a647 +ba00ffff +398b0205 +e710c5d7 +22000c85 +3200920a +0880820c +0a18d01f +22b85f09 +2c80ea09 +220cc5d7 +0701d716 +081a08d0 +0922b9df +7dd719ea +1f042210 +df080a00 +ea0922b9 +223dd70a +5f01d717 +32019200 +20f08204 +9f10c197 +081a1cc0 +10a118ce +225f04ea +085f3017 +17202fce +001f7006 +2057080a +09830063 +01570e22 +1a08d007 +22b95f09 +1681ea09 +1a1cc01f +78c5e70c +d77cc5e7 +9f182235 +090a1cc0 +7c08d607 +e725801a +c5e778c5 +2235d77c +08d60719 +07090a7c +047c20d4 +2dd70d4a +b8df1a22 +80ea0922 +7c8017d9 +17300304 +d01f6806 +671c0a34 +006368c0 +0000a047 +0daa0001 +1a222dd7 +0922badf +eab380ea +1cd00712 +2dd70dba +badf1a22 +80ea0922 +0cd607a1 +97064a68 +870c68c6 +1a087c81 +b85f3280 +107c85e7 +a6070f22 +ffff0000 +0205ba14 +c4171f8a +d70c7c14 +85e718c5 +1022107c +047c8417 +2dd7000c +80ea1a22 +7cc1d758 +c30833e3 +29d70433 +170833d7 +23047c80 +0403d730 +7de7b85f +d70f2210 +7de718c5 +07102210 +ff0000a6 +05ba14ff +d7d28902 +170c14c3 +000c046c +787cc407 +ce0d0a00 +e721a5d8 +c4800495 +c3570c22 +2c17007c +30170078 +057a001f +92a68902 +8214320f +c1570ce0 +18d01f0c +b85f090a +80ea0922 +1a281f38 +ea005f07 +d1d72f80 +38d02738 +d1c70197 +1f800a08 +1a0c2bc7 +107dd712 +d0070522 +d7081a2c +d717223d +d7399701 +60ea0079 +0792005f +00820432 +24d08f04 +0724d017 +ff0000a0 +0205baff +00924389 +00820032 +0cc5d708 +0000a647 +ba00ffff +2d890205 +06171b22 +92005f7c +82043200 +d01f0880 +5f080a18 +ea0922b8 +0cc1d723 +0010d3d7 +0414d3d7 +03d71c22 +d71d2208 +1e220c03 +221003d7 +1403d71f +0192005f +f0820432 +10c15714 +0a18d01f +22b85f09 +b980ea09 +a02b2817 +03000000 +1f700617 +ce0b0a00 +2208a5d8 +a180ea09 +2738d197 +011738d0 +0a08d187 +0cc3870f +17090a04 +00719731 +d18770ea +d70b0a08 +04221075 +091a009f +0922b9df +177280ea +70030470 +5a280708 +22ba5f09 +6180ea09 +06170e22 +08d00774 +b95f091a +80ea0922 +74c1d750 +000073d7 +03047017 +28230870 +d70803d7 +a387042b +ffff0000 +0205ba0c +73d75388 +75d70c0c +d7042210 +107de705 +75d70f22 +d7052210 +107de705 +31d71022 +0074c3d7 +78232817 +0803d704 +0f92005f +00820832 +18d01f08 +b85f080a +1fea0922 +d5d7b8df +14c5d72c +0000a647 +ba00ffff +01880205 +e710c5d7 +22000c85 +3200920a +0400820c +0a18d01f +22b85f08 +5f0bea09 +c69734d0 +005f1c0c +04320092 +1f040082 +080a18d0 +0922b85f +d0df07ea +92005f34 +82003200 +c0171cf0 +ce085f10 +0000a02f +08171400 +011f0117 +bbdf09aa +80ea0922 +0cc1d741 +2017285f +0617070f +171bea64 +00a00338 +97140000 +0003d701 +e714c5d7 +2022107d +288f31d7 +ba64c147 +3cd3d764 +0cc69700 +14c5d73c +22107de7 +92005f20 +820c320f +c19708c0 +38d1d70c +0a08d1c7 +0433c70c +79d7070a +1773ea00 +32039238 +08808204 +1f3cd1d7 +070a28d0 +ea28d05f +08d3c71a +df141a00 +212228d0 +087a001f +ea08d017 +d1d72980 +007e973c +107dd73c +00570622 +0000a047 +05ba3200 +27fe8602 +408091f8 +8f001700 +38170040 +00320192 +1714f082 +d3170cc1 +2697003c +1065d73c +01970622 +0000a007 +05ba3200 +67ce8602 +408090f8 +8f085700 +285f004f +c73cd1d7 +160a08d1 +121a281f +22107dd7 +0a300706 +d728df04 +69ea0079 +0000a187 +05ba3200 +279a8602 +408096f8 +00401f00 +1f6f801a +6a800a30 +800a281f +0445d765 +01d71622 +0a08d007 +107dd70b +001f0422 +d8ce0f0a +95e71ca5 +22e68004 +df09ea0c +107de7b8 +a1870f22 +32000000 +860205ba +96f82750 +5f004080 +35d70440 +d1d72222 +08d1c73c +7dd71b0a +07062210 +ce0d1a30 +e717a5d8 +03810495 +79d70c22 +9264ea00 +8204320f +385f14e0 +a1c7305f +32000000 +301f24aa +a1c7201a +32000000 +860205ba +97f82700 +1f004080 +061a0440 +04ea30df +58ea388f +071a301f +80ea07df +a5d9ce3e +c5e7e803 +57232274 +7a001f01 +2b80ea05 +d9ce3dd7 +d7e803a5 +0d2274c5 +a1c70157 +32000000 +850205ba +97f867b8 +57004080 +5f0474c2 +005f0048 +00320792 +1708f082 +81d70cc1 +81570010 +d1d70014 +c7305f38 +800a08d1 +1a301f31 +7dd72c80 +1f042210 +c7110a00 +ba0420d3 +0823c70b +00df064a +005f04ea +001f0197 +07ea040a +79d73957 +174eea00 +1700103c +9200142c +820c320f +c11708f0 +1081d70c +14815700 +38d1d700 +5738d027 +c7305f01 +800a08d1 +20d3c73b +34805a04 +801a301f +107dd72f +001f0422 +23c70b0a +df064a08 +5f04ea00 +1f019700 +ea040a00 +d7395707 +d3c70079 +054a0420 +ea08d1d7 +103c1744 +142c1700 +320f9200 +0ce0820c +d70cc157 +d02738d1 +c7019738 +180a08d1 +22107dd7 +1a280705 +223dd708 +9701d717 +0079d739 +079267ea +f0820432 +0cc1170c +d710c157 +d02738d1 +c7019738 +800a08d1 +0c23c71e +7dd7161a +07052210 +d70d1a28 +d717223d +d7019701 +61ea0041 +08320f92 +d708c082 +79970cc1 +0073d700 +0873c300 +2235d708 +3203921a +0cf08204 +970cc157 +29170069 +221075d7 +0a001f04 +1729d717 +78030478 +0cd00708 +7ea3061a +2dd70c08 +b8df2422 +22106de7 +222dd70f +07019725 +071a08d0 +80ea2017 +1075d714 +001f0422 +3117080a +242235d7 +0f922017 +e0820432 +0cc1570c +2738d1d7 +019738d0 +071a3947 +ea08d017 +08d1c71e +39470d0a +3997090a +ea0079d7 +08d1c772 +d017071a +1704ea08 +32079230 +0ce08204 +270cc157 +01973cd0 +c73cd1d7 +800a08d1 +107dd71c +28070622 +7b970b1a +79d70000 +9707ea00 +0079d739 +d02763ea +d701973c +07923cd1 +e0820432 +38d1970c +d187285f +d7150a08 +107dd731 +001f0422 +7943050a +00799708 +28176aea +00320792 +970ce082 +285f38d1 +0a08d187 +d731d720 +04221075 +ba082bc7 +ea08df06 +07085f04 +57051a08 +79970879 +175fea00 +32079228 +0ce08200 +5f38d197 +08d18728 +31d71b0a +22107dd7 +0a001f04 +20d3c70b +43055a04 +79970879 +1764ea00 +32079228 +0ce08200 +d197285f +08d18738 +31d7200a +22107dd7 +0a001f04 +20d3c710 +c70a5a04 +05ba082b +97087957 +5fea0079 +07922817 +00820032 +00a63404 +df069a0c +5f04ea00 +32009200 +08808204 +000c81d7 +0a10c01f +00a1db0a +ea010000 +ffa1eb08 +17feffff +92000c3c +82083201 +d8ce0400 +b8df09a5 +220cc5d7 +32009226 +04008204 +ce10c5d7 +df09a5d8 +0c85e7b8 +92272200 +82083200 +d8ce0400 +d8ce1fa5 +c5d70aa5 +9226220c +82043200 +c5d70400 +a5d8ce10 +a5d8ce1f +0c85e70a +92272200 +82083200 +c5d70c80 +78c5e70c +01d72822 +076a001f +ea78c017 +d7b8df0b +0229223d +01925782 +80820432 +0cc5d708 +01d71222 +046a001f +b8df08ea +292205d7 +04320192 +d7088082 +a6470cc5 +ffff0000 +0205ba00 +1b222b82 +001f01d7 +08ea046a +05d7b8df +01922922 +80820432 +0cc5d708 +0000a647 +ba00ffff +05820205 +01d72a22 +046a001f +b8df08ea +292205d7 +04320192 +220cc082 +00a0072b +baffff00 +e1810205 +381f0197 +a0070f6a +ffff0000 +810205ba +5f0bead0 +223dd7b8 +c1810229 +00320392 +d7088082 +a6470cc5 +ffff0000 +0205ba00 +2c22af81 +001f01d7 +08ea046a +05d7b8df +01922922 +80820432 +10c5d70c +0000a647 +ba00ffff +89810205 +e70cc5d7 +2d2278c5 +001f01d7 +c017076a +5f0bea78 +223dd7b9 +69810229 +08320192 +d7088082 +c5d710c5 +d711220c +6a001f01 +5f08ea04 +2205d7b9 +32019229 +08808208 +220cc5d7 +1f01d70b +ea046a00 +d7b8df08 +92292205 +82043201 +c5d70880 +d72e220c +6a001f01 +df08ea04 +2205d7b8 +32019229 +08808204 +01d72f22 +046a001f +b85f08ea +292205d7 +00320192 +d7088082 +d3c738d1 +800a0008 +107dd726 +001f0422 +7817170a +1045d700 +001f0422 +3dd70b0a +d1d72422 +d705ea38 +58ea0079 +04120192 +af28f082 +a57c5cc4 +64c4af0c +201f20df +5f9a800a +87205f30 +000000a1 +8a80aa32 +0000a187 +05ba3200 +279a8002 +408096f8 +04401f00 +9f6e800a +801a0040 +0445d768 +01571622 +0a08d007 +106dd70b +001f0422 +d8ce0d0a +95e719a5 +221b8104 +38d1d70c +22107dd7 +0a300706 +0079d707 +681774ea +08680304 +1a047807 +7dd72b80 +1f042210 +21800a00 +22046dd7 +7c061712 +0000a187 +05ba3200 +672e8002 +408096f8 +04485f00 +308f20df +ea73bfea +bc2f67bf +ef20bf02 +0f925cc4 +00820032 +df302204 +009218d0 +b85f0032 +b95f08ea +b9df04ea +00003122 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b8df0000 +2c0495e7 +5f0cc5d7 +920122bb +82043200 +c1d704c0 +00a1c718 +ba090000 +5f381720 +a02fce08 +0a000000 +01970817 +185f3897 +00a0afce +d70a0000 +5f04ea11 +a018ce30 +57300330 +0e0714c0 +02055a10 +07140a8c +ce000c81 +8330a098 +d7088f38 +101e0708 +8b02055a +831714f3 +0392000c +00821032 +0cc50400 +040caa30 +aa0c39a6 +ea00df06 +92005f04 +82081200 +c19700c0 +14c1d70c +5a103e07 +c08b0205 +37e5d8ce +bf02bc2f +0a001fd0 +38575680 +0e07088f +02055a10 +d8cea68b +bc2f31e5 +1fb6bf02 +3c800a00 +5a103e07 +908b0205 +37e018ce +30a098ce +27ce1023 +000000a0 +8f38570a +100e0708 +8b02055a +e058ce73 +a098ce31 +03106330 +18041708 +ea00df00 +92005f04 +82103203 +c4af0800 +1ca57c78 +d77cc4af +c5d77cc5 +0702220c +000000a4 +4a007c54 +00a40710 +7c630000 +df06aa00 +5f04ea00 +78c4ef00 +04320092 +d704c082 +781f0cc1 +c7360a04 +000000a3 +2daa040c +8f047817 +00a00707 +ba0b0000 +008b0205 +0c90f197 +00789700 +0000a0ab +10570300 +091a081f +1a04791f +1f308f04 +3b4a007a +0000a3c7 +aa006300 +04781f3d +a3c73e0a +0c000000 +c73baa04 +36aa0833 +0000a3c7 +5a0c1800 +00a3c72d +103c0000 +a3c7245a +3c000000 +ea1b5a14 +c717ea04 +000000a3 +04ea1864 +0a5a0cea +06ea04ea +04ea00df +0392005f +00820432 +0c805f04 +0cc09704 +08df03df +005f00e2 +374e059a +7c061700 +04320092 +97040082 +03df0cc0 +00e2095f +059a005f +1700374e +00927c06 +f0820432 +0c801718 +a0174e00 +0c8097f8 +a0974e04 +a0974e10 +17100308 +00977c06 +afce185f +830000a0 +a0974ed6 +0c801708 +00a02b00 +83ff0000 +ce185f00 +0000a0af +18976400 +d7741617 +101710c1 +2fce085f +000000a0 +5f08173c +a02fce08 +3c000000 +03d70817 +5f10170c +a02fce08 +3c000000 +085f0817 +00a02fce +d73c0000 +10171003 +2fce085f +000000a0 +1403d73c +040c8017 +2fce085f +000000a0 +a027ce64 +60000000 +000c8097 +afce185f +000000a0 +5f100364 +a02fce08 +64000000 +971803d7 +185f7cc0 +00a0afce +97d68300 +47105718 +050000a0 +5f075ab5 +1bea78c0 +5f7cc097 +a0afce18 +d6830000 +a0a31897 +b5050000 +1617108f +78c05778 +0997088f +5f78c097 +a0afce18 +b5050000 +974e1897 +120f02a0 +08171117 +2fce085f +050000a0 +170197b5 +00a02b20 +1f030000 +87161a00 +010000a1 +a30aba6e +010000a1 +ea04ea6e +8714ea1a +010000a1 +a30aba6d +010000a1 +ea04ea6d +ea208f06 +1f28df4c +17371a29 +00a02b20 +1f030000 +87171a00 +000000a1 +a30aba1d +000000a1 +ea05ea1d +14ea3d80 +0000a187 +0aba1c00 +0000a1a3 +04ea1c00 +21ea28ea +078f2817 +0000a007 +05ba0b00 +87b98802 +000c90f1 +f1a309ba +ea000c90 +8f07ea04 +a6bfea28 +d710c1d7 +2bd70023 +0833d704 +08320f92 +d720f082 +78170cc1 +4e060f00 +cefea017 +0000a027 +0197b505 +0f007897 +00a0ab16 +17030000 +0a101f11 +17308f04 +a027ce10 +6d010000 +28df0183 +8f047817 +60061707 +281718ea +a007078f +0b000000 +880205ba +90f18343 +288f000c +ba60c147 +1a201f67 +04791f09 +308f04ba +78033017 +97078f08 +00a00301 +57b50500 +170f8f00 +7897780e +a0a7ce0c +3c000000 +ce107883 +0000a0a7 +78833c00 +a0a7ce14 +64000000 +17187883 +08176816 +00a027ce +4ed68300 +03f8a097 +6c061710 +974e0097 +1417e8a0 +a02b0410 +ffffff00 +08a0174e +ab68c097 +000000a0 +171003ff +92001004 +8208320f +c5d70880 +d703220c +04220cc5 +0a1a001f +0522b85f +04ea01d7 +3817385f +04320192 +d7088082 +04220cc5 +0a1a001f +0522b8df +09ea01d7 +220cc5d7 +17385f06 +32019238 +10808204 +1774c4af +008f14c0 +c057057f +0e14af10 +c4af0000 +1ca57c10 +c5d73caf +10c5d714 +a0070722 +16000000 +c5e73d4a +d7b85f78 +c5d714c5 +1f082210 +073c0a00 +000000a6 +3c1a7813 +b95f3dd7 +d714c5d7 +082210c5 +3b0a001f +df047de7 +14c5d7ba +2210c5d7 +ea001f08 +0a3bea04 +087de739 +08a5d8ce +ea14c5d7 +d73dea04 +082210c5 +3dea04ea +390a001f +ce0c7de7 +ea0ba5d8 +d73cea04 +c5d714c5 +1f082210 +e73d0a00 +04ea107d +d8ce3eea +c5d70ea5 +10c5d714 +001f0822 +3cea04ea +7de73a0a +ea04ea14 +a5d8ce3d +14c5d711 +ea10c5d7 +2234ea04 +0a001f08 +187de72e +27ea04ea +14a5d8ce +1fea04ea +d714c5d7 +082210c5 +130a001f +0fea04ea +09223dd7 +04ea001f +801a05ea +22b95f09 +d70bea05 +3dd70cc5 +005f0a22 +9274c4ef +820c3201 +c4af10f0 +10c01774 +057f008f +af0cc057 +00000e14 +170cc4af +815714c1 +285f0018 +c5d7305f +0cc5d710 +a1470b22 +0b000000 +1f6380aa +5e801a30 +385f30df +301f38ea +2897360a +00a0a7ce +57030000 +47384310 +000000a0 +0205ba24 +58ce0686 +001091e0 +0000a06b +20975f00 +16073883 +02055a10 +06eaee85 +0dea15ea +0c82e044 +df061a00 +5f04ea00 +8f019700 +ba391f38 +288fb3bf +179abfea +182c1730 +74c4ef00 +14120f92 +af0c8082 +c01778c4 +7f008f14 +10c05705 +000e14af +10c4af00 +af1ca57c +18785f3c +d714c5d7 +072210c5 +0000a007 +3c4a1200 +5f087de7 +14c5d7b8 +2210c5d7 +0a001f08 +047de73d +c5d7b9df +10c5d714 +bf02bc2f +0a001f11 +df3dd73c +14c5d7bb +2210c5d7 +0a001f08 +0c7de73d +3dea04ea +0aa5d8ce +d714c5d7 +082210c5 +04ea001f +3a0a3cea +ce107de7 +d70da5d8 +c5d714c5 +ea04ea10 +1f082230 +e72a0a00 +d8ce147d +04ea10a5 +c5d71fea +ea04ea14 +10c5d718 +001f0822 +3dd70f0a +04ea0922 +001f07ea +5f09801a +ea0522b9 +0cc5d70b +0a223dd7 +c4ef005f +32019278 +1000820c +7c74c4af +c4af18a5 +1ca57c7c +d778c4af +042218c5 +091a001f +0522b8df +d7bb80ea +c5d778c5 +ce022218 +d716a5d8 +d8ce7cc5 +95e716a5 +00222d04 +13a5d8ce +d8ceb85f +c5d716a5 +d70c227c +5f007885 +a5d8ceb9 +7cc5d716 +85d70c22 +badf0478 +16a5d8ce +227cc5d7 +7885d70c +a5d8ce08 +a5d8ce08 +7cc5d716 +85d70c22 +d8ce0c78 +d8ce0ba5 +c5d716a5 +d70c227c +ce107885 +ce0ea5d8 +d716a5d8 +0c227cc5 +147885d7 +11a5d8ce +16a5d8ce +227cc5d7 +7885d70c +a5d8ce18 +a5d8ce14 +7cc5d716 +c5d70c22 +0cc5d710 +16a5d8ce +227cc5d7 +10c5d70d +220cc5d7 +14041707 +ef005f00 +009274c4 +c0821032 +6cc4af18 +af14a57c +a57c7cc4 +78c4af1c +2218c5d7 +1a001f04 +22b8df09 +ca80ea05 +d778c5d7 +022218c5 +12a5d8ce +ce7cc5d7 +e712a5d8 +44800495 +85d70022 +b85f0878 +12a5d8ce +227cc5d7 +7880170c +ce078f04 +0000a027 +01970300 +2aea385f +38033017 +0000a007 +05ba2400 +df9d8302 +47384309 +000000a0 +0205ba11 +e7148e83 +00108190 +388f007c +56ba391f +007885d7 +d8cebbdf +c5d712a5 +d70c227c +ce0c7885 +ce0aa5d8 +d712a5d8 +0c227cc5 +107885d7 +0da5d8ce +12a5d8ce +227cc5d7 +7885d70c +a5d8ce14 +a5d8ce10 +7cc5d712 +c5d70c22 +0cc5d710 +12a5d8ce +227cc5d7 +10c5d70d +220cc5d7 +14041707 +ef005f00 +03926cc4 +80821032 +68c4af1c +af14a57c +a57c7cc4 +78c4af1c +af08a57c +c5d774c4 +d70e2274 +6a001f01 +74c5d736 +ce6cc5e7 +d712a5d8 +0f227cc5 +c5d701d7 +0cc5d710 +12a5d8ce +0aa5d8ce +12a5d8ce +227cc5d7 +10c5d710 +220cc5d7 +14041707 +ef381700 +019268c4 +80820c32 +74c4af10 +af08a57c +c5d77cc4 +d70e227c +6a001f01 +7cc5d713 +001485e7 +d710c5d7 +11220cc5 +c4ef01d7 +32019274 +1c80820c +7c68c4af +c4af14a5 +1ca57c7c +7c78c4af +c4af08a5 +74c5d774 +01d70e22 +346a001f +e774c5d7 +d8ce6cc5 +c5d712a5 +d70f227c +10c5d701 +ce0cc5d7 +5f09a5d8 +a5d8ceb8 +7cc5d712 +c5d71022 +0cc5d710 +04170722 +38170014 +9268c4ef +820c3201 +c4af1c80 +14a57c68 +7c7cc4af +c4af1ca5 +08a57c78 +d774c4af +0e2274c5 +001f01d7 +c5d72e6a +6cc5e774 +12a5d8ce +227cc5d7 +d701d70f +c5d710c5 +a5d8ce0c +7cc5d712 +c5d70d22 +0cc5d710 +04170722 +38170014 +9268c4ef +820c3201 +c5d70880 +d70e220c +7a001f01 +d7b8df0a +ea122205 +9202ea04 +82043201 +c5d70880 +d713220c +7a001f01 +d7b8df0a +ea122205 +9202ea04 +82043201 +c5d70880 +10c5d714 +220cc5d7 +1f01d714 +df0a7a00 +2205d7b9 +ea04ea12 +32019202 +0880820c +d714c5d7 +c5d710c5 +d715220c +7a001f01 +d7b9df0a +ea122205 +9202ea04 +820c3201 +c5d70c80 +78c5e714 +d710c5d7 +11220cc5 +001f01d7 +b9df0a7a +122205d7 +c01707ea +0205ea78 +01923681 +80820c32 +14c5d70c +d778c5e7 +c5d710c5 +d70f220c +7a001f01 +d7b9df0a +ea122205 +78c01707 +810205ea +3201920b +0c80820c +d778c5e7 +c5d710c5 +d716220c +7a001f01 +d7b95f0a +ea122205 +78c01707 +800205ea +320192e3 +0c808208 +d778c5e7 +c5d710c5 +d717220c +7a001f01 +d7b95f0a +ea122205 +78c01707 +800205ea +320192bb +0c808208 +d778c5e7 +c5d710c5 +d718220c +7a001f01 +d7b95f0a +ea122205 +78c01707 +800205ea +32019293 +0c808208 +d778c5e7 +c5d710c5 +d719220c +7a001f01 +d7b95f0a +ea122205 +78c01707 +800205ea +3201926b +04008208 +80049067 +10d09757 +0aa018ce +ce00030e +0c1fa498 +a498ce00 +ce040c1c +0c1fa498 +a498ce08 +ce0c0c1e +0c1fa498 +a498ce10 +ce140c1e +0c1fa498 +a498ce18 +ce1c0c1f +0c1ea498 +a498ce20 +ce240c1f +0c1ea498 +a498ce28 +222c0c1f +3200921a +eab85f00 +22b95f04 +0000001b +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +c1d710f0 +1481970c +10c01700 +3007078f +3607174a +02055a10 +18ced681 +a0043ee0 +8f061a20 +1764ea30 +078f10c0 +0f4a3007 +5a103607 +b8810205 +1a3ee01c +ea005f07 +31178a80 +8f10c017 +4a200707 +10260724 +8102055a +e018ce9b +20a0043c +2607130a +02055a10 +e01c8a81 +8f060a3c +1757ea20 +17302320 +c0577406 +470f8f1c +570a5a00 +0f8f1cc0 +5f740e17 +74c01728 +0617078f +571eea70 +07284330 +055a100e +07518102 +055a1c2e +14498102 +188539e7 +47288f00 +61ba70c1 +0774c017 +055a1c06 +14318102 +180080a7 +df219700 +14341700 +320f9200 +04008214 +000c8504 +0417aa61 +000c7aa4 +18ce10aa +58ce61a0 +082341a0 +000c0420 +04320092 +9708c082 +385f0cc1 +8f10c017 +4a380707 +103e0720 +8002055a +37e01ce3 +3e07130a +02055a10 +e5e7d680 +8f012237 +925bea38 +82083203 +c1570ce0 +5f305f0c +0712ea38 +0000003d +7708ba20 +8f049a39 +c7388f30 +000000a1 +176aba1f +32079230 +0c008204 +1778c4af +008f18c0 +c057057f +0e14af14 +c4af0000 +7cc05f14 +ce7cc5e7 +d70cc5d8 +c5d718c5 +1f022214 +d7350a00 +c5d720c5 +7cc5d71c +c5d7b85f +14c5d718 +c08f0322 +28c5d77c +d724c5d7 +c5d718c5 +d7042214 +7cc5d705 +d718c5d7 +032214c5 +c01f2fea +d7170a10 +c5d728c5 +18c5d724 +2214c5d7 +00a41405 +15ea001c +d720c5d7 +c5d71cc5 +14c5d718 +a4140522 +ef002400 +009278c4 +00822032 +32009204 +22b85f00 +00000006 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +c4af10e0 +10c01770 +057f008f +af0cc057 +00000e14 +170cc4af +008f18c0 +c057057f +0e14af14 +c4af0000 +ceb85f14 +e70ca5d8 +012278c5 +001f0197 +5f56806a +070222b8 +ff0000a0 +0205baff +01577385 +c1d70322 +10d3d778 +10c5d700 +220cc5d7 +0403d704 +d718c5d7 +042214c5 +970803d7 +221078c6 +472dd705 +ff0000a6 +05ba00ff +223e8502 +00a00702 +baffff00 +31850205 +30170157 +9270c4ef +82103207 +03220480 +1008d687 +0522111a +0ea5d8ce +2c0495e7 +80ea0622 +1091d721 +1095e700 +e7072204 +22081095 +10d5d707 +001f0822 +3e97027a +5f052210 +32019200 +00008200 +7a0cc01f +08801f0d +17071a7c +7c080cc4 +7c08801f +00df061a +005f04ea +08120092 +d7000082 +c5d70cc5 +d4bf0208 +020a001f +08120092 +af0c0082 +a57d74c4 +c4af5800 +7cc05f78 +05d70922 +bf02bc2f +0a001fb3 +0a22ae80 +bc2f05d7 +1fa5bf02 +97800a00 +05d70b22 +bf02bc2f +0a001f97 +c5d78080 +18c5d71c +d714c5d7 +0c2210c5 +bc2f05d7 +1f7dbf02 +5d800a00 +2278c5d7 +0a001f0d +c5d74180 +d70e2278 +02bc2f05 +001f62bf +0f222e0a +bc2f05d7 +1f55bf02 +d7210a00 +c5d71cc5 +14c5d718 +7f10c5d7 +05d70cc0 +bf02bc2f +d710225e +02bc2f05 +0bea55bf +187885d7 +bf02bc2f +d711224a +02bc2f05 +122241bf +bc2f05d7 +2238bf02 +2f05d713 +2fbf02bc +05d71422 +bf02bc2f +7cc01726 +9274c4ef +82143200 +b85f0480 +bb5fb8df +0015b5e7 +01d71622 +047a001f +b8df12ea +1722bb5f +001f01d7 +04ea047a +0192005f +00820032 +e7b8df00 +5f3b0495 +a5d8ceba +d718220a +92192205 +82143200 +b8df0000 +3c0495e7 +d8ceb95f +18220aa5 +18320092 +02000082 +00927b83 +00821832 +18c5d700 +d714c5d7 +c5d710c5 +1ab5e70c +921b2200 +82103200 +c5d70480 +14c5d718 +d710c5d7 +1c220cc5 +001f01d7 +d5d7097a +2205d708 +3d83021d +10320192 +d7000082 +c5d718c5 +10c5d714 +e70cc5d7 +22001eb5 +3200921b +00008210 +df08d5d7 +021d22bf +00921383 +f0821032 +60c4af20 +8f10c017 +57057f00 +14af0cc0 +af00000e +c1970cc4 +04a57c14 +7d70c4af +af0001a5 +c05f68c4 +18d01f64 +b8df131a +3d0495e7 +d8ceb85f +18220aa5 +cedb80ea +0001a5d9 +e768c5d7 +d9ce64c5 +d70001a5 +1f221cd5 +800a001f +2ea404b3 +1a1a0068 +0168801c +d9ce141a +d70001a5 +c5d768c5 +0cc5d710 +12ea2022 +01a5d9ce +68c5d700 +d710c5d7 +21220cc5 +01a5d9ce +68c5d700 +01d72222 +806a001f +70c5d770 +05d7ba5f +7a00c81f +69820205 +226cc5e7 +d7015723 +00c81f3d +8202057a +17242258 +6a281f01 +d7ba5f35 +ba5f14d5 +2270c5d7 +0a001f25 +18c5d717 +d9ce35d7 +d70001a5 +b5e768c5 +1b22001a +a40433ea +1a007024 +18c5d71b +04ea35d7 +d9ce12ea +d70001a5 +b5e768c5 +1b22001e +bfea13ea +10c5d739 +5f0cc5d7 +a5d8ceb9 +ef18220a +0f9260c4 +00821032 +08d5d700 +1d22bfdf +92e28102 +82103200 +c5d70000 +ce26220c +e70fa5d8 +223e0495 +32009206 +00008204 +c5d70322 +0cc5d710 +081095d7 +05222722 +d710c5d7 +28220cc5 +08320092 +22000082 +10c5d703 +d70cc5d7 +22041095 +d7052227 +c5d710c5 +9228220c +82083200 +c4af0400 +10c0177c +057f008f +af0cc057 +00000e14 +ce0cc4af +0001a5d9 +d71cd5d7 +c5d710c5 +df20220c +005f18d0 +927cc4ef +82083200 +d5d70000 +22bfdf08 +3200921d +10008208 +7c70c4af +c4af0ca5 +a5d8ce78 +0495e70f +c5e74e80 +a5d8ce74 +78c5d70b +001f2922 +c0172d6a +00a00774 +ba0a0000 +11810205 +0080a714 +d8ce0078 +c5d70ba5 +7cc5e778 +00572a22 +076a081f +ea7cc017 +7fa01708 +efffffff +009270c4 +00820032 +922b2200 +82003200 +c5d70400 +10c5d714 +e70cc5d7 +2c227cc5 +081f0057 +c01f0b6a +df060a7c +5f04ea00 +32009200 +0000820c +5f0cc5d7 +0495e7ba +2d225e80 +1a1a001f +95e7b8df +ce638004 +ce1fa5d8 +220ea5d8 +47005718 +061a10c0 +04ea00df +0092005f +00820832 +10c01f00 +b8df227a +800495e7 +a5d8ce64 +a5d8ce20 +5718220e +10c04700 +00df061a +005f04ea +c5d722ea +a5d8ce0c +0495e708 +2d226580 +0a1a001f +00572b22 +06da081f +04ea00df +0092005f +80820832 +0cd01700 +d7100697 +d3d710d1 +d3d70008 +a4940808 +94001480 +011414a4 +1433a494 +22a49402 +a4940314 +5f001c00 +019218d0 +b85f0032 +b95f08ea +b9df04ea +00002e22 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +c4af10e0 +10c19774 +0001a57d +38df2caf +007018ce +ea700617 +00a1c723 +baff0000 +798d0205 +0f8f3857 +0000a047 +05baff00 +146a8d02 +002977e7 +c1c7388f +ce5cba70 +07007018 +000000a0 +ce15aaff +47007058 +000000a0 +0205baff +a714438d +d9ce0029 +d70001a5 +0cc5d72d +c4ef0122 +32079274 +04008208 +95e7b8df +c5d72c04 +22ba5f0c +32009202 +0cf08204 +170cc157 +18ce10c1 +01d70068 +006098ce +061a0087 +04ea08df +0997085f +300a301f +2c0a381f +0000a1c7 +05baff00 +c7e68c02 +000000a1 +0205baff +e704db8c +00006f67 +00df061a +005f04ea +3f8f0197 +301750ea +08320f92 +170cf082 +c1570cc1 +6818ce10 +ce01d700 +8f006098 +1a008717 +ea08df06 +97085f04 +0a301f09 +0a381f34 +8f385730 +00a04708 +baff0000 +898c0205 +0000a1c7 +05baff00 +047e8c02 +006f61e7 +df061a00 +5f04ea00 +8f019700 +174cea3f +320f9230 +0ce08208 +5f0cc157 +0cd1d730 +1b1a301f +0a08d1c7 +047dd716 +03222dd7 +060a001f +05ea30df +ea0079d7 +92381765 +82043207 +c4af28f0 +01a57d5c +68c4af00 +8f10c017 +17008f07 +18c05701 +088f0f8f +a0070997 +ff000000 +a0470aaa +ff000000 +d8ce0cba +95e723a5 +04222d04 +a0072017 +ff000000 +8b0205ba +680414f8 +5738df00 +580e1720 +381723ea +0607078f +02055a10 +a1c7d78b +ff000000 +8b0205ba +80e714cc +68000c87 +c7388f00 +5cba58c1 +006885e7 +06170522 +08d00774 +d8ce0d1a +95e72ba5 +22518004 +a058ce04 +d730430d +00c81f0d +8b02057a +70c5e79c +06170622 +7a001f60 +a5d8ce0d +0495e735 +04227d80 +0370c017 +000000a0 +5701570c +00a04730 +baff0000 +6d8b0205 +df000a14 +17309738 +22ea5816 +078f3817 +5a180607 +4d8b0205 +0000a1c7 +05baff00 +14428b02 +146f80e7 +388f0000 +ba58c1c7 +1cc4175d +2c170870 +84170470 +00700874 +7470c417 +5cc4ef08 +14320f92 +570ce082 +81d70cc1 +305f0c10 +1c1a301f +0a08d1c7 +047dd717 +c07f2dd7 +0a001f14 +ea30df06 +0079d705 +381764ea +0c320792 +570ce082 +81d70cc1 +305f0810 +1b1a301f +0a08d1c7 +047dd716 +03222dd7 +060a001f +05ea30df +ea0079d7 +92381765 +82083207 +c19718f0 +58a38410 +df061a01 +5f04ea00 +1f015700 +27090a00 +700007b6 +b62707ea +d7700003 +05220cc5 +d0070117 +d70d1a08 +d5d70cc5 +ea082218 +c5d74080 +d725d770 +d7092235 +08d00701 +35d70c1a +221cd5d7 +2680ea08 +080a281f +6c0c7e17 +7e1706ea +c01f6c08 +d70b1a6c +1cd5d735 +09ea0822 +146cc417 +92005f00 +820c320f +c19718f0 +1481d70c +2235d700 +07015705 +0c1a08d0 +d5d735d7 +ea082218 +2dd75c80 +2210c5d7 +0701170a +080a08d0 +ea0861d7 +c5e74680 +10c5d770 +0b2235d7 +1f740617 +d70d7a00 +d5d710c5 +ea082220 +c1d72c80 +a5d8ce70 +d7b85f0f +170c223d +40176c06 +68061708 +1fa5d8ce +10a5d8ce +0c223dd7 +d768c003 +17005f01 +9200143c +820c320f +c1d714f0 +c7205f0c +800a08d1 +04781736 +0157060f +1a00401f +d722ea04 +5f25d725 +10c5d7b8 +220045d7 +1f01970d +0d1a10c0 +097a001f +0c08d3d7 +d70a80ea +49ea0c79 +0f92005f +80820832 +10c1d704 +030cc017 +5f078f38 +382fce08 +27ce0817 +12019238 +1ce0820c +9768c4af +7c000c81 +c4af10a5 +70c5d770 +100885d7 +0c088057 +badf0dd7 +01d70e22 +057a001f +178280ea +10087084 +10805700 +43080f00 +000000a0 +570f8f10 +1f0dd709 +057a00c8 +e71a8902 +06226cc5 +001f01d7 +80ea057a +a5d8ce54 +6cc5d710 +0208c5d7 +019783bf +0a6cc007 +d735d720 +0f226cc5 +001f01d7 +80ea057a +6cc5d730 +01d71022 +057a001f +172280ea +5f007034 +d7047080 +85d770c5 +80571008 +0dd70c08 +ffa5d8ce +01d70e22 +3417005f +c4ef000c +12079268 +0400820c +0c088017 +170cc003 +df7c0804 +92780880 +82081200 +80170400 +c0037c08 +0804170c +0880df7c +12009278 +10c08208 +7c088017 +1f004197 +0a780880 +5f385f0a +ea780880 +df3a5f0c +08c5d7b8 +57cbbf02 +d7098f38 +d73dd70d +920c2235 +82041203 +bbdf0880 +8057b85f +4dd77c08 +d70c2200 +d7b8df01 +bf0208c5 +923817a1 +82041201 +d8ce0880 +b85f0fa5 +7c088057 +22004dd7 +5f01d70c +08c5d7b9 +177fbf02 +12019238 +08808204 +7c088017 +5f0041d7 +08c5d7ba +1767bf02 +12019238 +0cd08204 +0fa5d8ce +c5d7b85f +4e0c220c +9702a017 +a5d8ce01 +a5d8ce1f +0cc5d710 +174e0c22 +01d702a0 +9708c097 +50570850 +2c48576c +30470e0f +c0d7144a +0858d708 +576c5857 +0e0f2c48 +075a0047 +ea14d017 +08c0573c +17084857 +a1877448 +fcff0300 +870205ba +46e0278c +10041700 +08c11700 +d7086117 +a1c77460 +fcff0300 +870205ba +5fe0e770 +141c1700 +ea04ea00 +92005f04 +8210120b +c5e71480 +7cc5e778 +000c85d7 +0208c5d7 +01d75ebf +047a001f +c5e71cea +7cc5d774 +2278c5d7 +1f01d70b +ea047a00 +74c41709 +005f000c +08120192 +e7148082 +c5e778c5 +0c85d77c +08c5d700 +d725bf02 +7a001f01 +e71cea04 +c5d774c5 +78c5d77c +01d71122 +047a001f +c41709ea +5f000c74 +12019200 +0ce08208 +9f10c157 +1708ba2b +80ea14d0 +9f2817ab +0205ba03 +ef7dd786 +001404d8 +00690019 +00690069 +00830069 +385f0090 +ce8780ea +5f0fa5d8 +0c85d7b8 +970c2200 +4a009f01 +0880173b +0840176c +30aa0187 +70088057 +178f3097 +0000a087 +05baff0f +4e8a8602 +6702a097 +d7004af0 +d8ce0c4d +b85f0fa5 +000c85e7 +385f1222 +d1d705ea +5736ea14 +a0bf0880 +170f0097 +05ba119f +035a8602 +0c004af4 +ea385f00 +0c85e71c +02bc2f00 +01d7ecbe +85e70fea +bc2f000c +d718bf02 +1702ea01 +12079238 +10f0820c +d714c157 +c5d70cc5 +7cbd0208 +305f385f +2e0a281f +2a1a381f +0208c5d7 +011796bd +a18705d7 +feffff3f +860205ba +86f5e700 +c5d70010 +0cbf0208 +308f01d7 +52ea2f8f +0f923817 +f0821012 +08801714 +10c0030c +c1170157 +0cc19714 +301f385f +a1c724da +feffff3f +850205ba +3fa1c7c4 +bafeffff +b9850205 +676ff797 +360f0000 +5cea388f +10120f92 +a480f082 +60bfc4af +af10a57c +17a0bfc4 +a02b10c0 +03000000 +0b1a001f +0000a607 +5a109c00 +14d01708 +177784ea +d76c0cc6 +a3c76cc1 +80143322 +1f2f1a00 +2a0a0878 +0000a3c7 +aa080010 +0c7a1f21 +78171c4a +00a02b34 +1f030000 +170f1a00 +a02b2c78 +03000000 +080a001f +ea14d017 +b95f3484 +d7087dd7 +bb0208c5 +a0174ebc +64061701 +08a5d8ce +d70c7dd7 +bb0208c5 +a0174ea8 +600617ff +83107897 +78831478 +1c788318 +83207883 +78832478 +a0974e28 +5c161702 +80a058ce +4364c043 +43104300 +0e172c78 +08781758 +04a0174e +43540617 +08d70cc0 +172c78e3 +c057741e +58c0430c +ce700e17 +d710a5d8 +c5d7307d +49bb0208 +ce4c0617 +9710a5d8 +974e0c78 +105702a0 +d7347843 +08c5d70d +172ebb02 +d8ce4806 +7dd710a5 +08c5d738 +171ebb02 +c0574406 +58c0430c +4354c043 +78434cc0 +bf0e1734 +58c097a4 +8354c083 +c0834cc0 +17008348 +c0875016 +17080a10 +83ea14d0 +087e1759 +40c61740 +c0dfb8bf +c607b4bf +ba40b8bf +bfc11708 +1705eab8 +b85f40c1 +974e2097 +15d704a0 +b0bfc5e7 +01571322 +046a001f +278f04ea +067a001f +601a201f +057a001f +071383ea +5ab8bfc1 +bf261706 +bfc0dfb8 +172057ac +ea5cbf0e +bfc0573b +470f8fac +0f0000a0 +0205baff +574ef383 +f02702a0 +00b0bf81 +c0970197 +178fb4bf +0000a087 +05baff0f +4ed68302 +a702a097 +007082f0 +0dea04ea +8f0c0297 +8fb4bfc0 +07acbfc0 +bf5cbfc6 +b4bfdaac +1f402623 +bf1a40c0 +0cc4175c +1700a0bf +00a0bf80 +174cc003 +04a0bf04 +5748c003 +bf0c1700 +c04308a0 +17081744 +5774bf06 +c0434cc0 +44c04348 +98bf0e17 +7dd7ba5f +08c5d73c +d7fab902 +c0033c03 +009798bf +ba10c087 +ea08df06 +17085f04 +979cbf0e +8398bfc0 +c0873c78 +df061a10 +5f04ea00 +bf061700 +0a081f64 +3c7dd72b +7a00c81f +39830205 +6cbfc5e7 +01570622 +057a001f +171b82ea +bf6cbfc4 +c6170ca0 +70bf74bf +80971aea +8308a0bf +141744c0 +d70ca0bf +c374bfc0 +1e173c78 +789770bf +a0974e08 +d715d702 +d8ce70c5 +bc2f80a5 +57b9bc02 +7a001f01 +d681ea05 +d70c7dd7 +cea4bfc5 +4380a058 +0dd764c0 +bc02bc2f +1f01579b +ea057a00 +58ceb881 +c04380a0 +60c04364 +bc2f0dd7 +2709ba02 +06171078 +c0df94bf +80ea84bf +bfc0df79 +bfc05790 +470f8f84 +ffff3fa0 +0205bafe +f0178b82 +0094bf81 +5cbf0617 +2f4a80ea +74ba02bc +8cbf0617 +4358c057 +004754c0 +c0570baa +470e0f50 +17085a00 +81ea14d0 +0cc01755 +8cbfc003 +88bf0617 +84bfc5d7 +88bfc5d7 +bb02bc2f +1f01575b +ea057a00 +c08f3481 +c60790bf +90bf5cbf +8fb3bfba +9f84bfc0 +ba84bfc3 +b8df86bf +2f047de7 +30bb02bc +001f0157 +81ea057a +047c1709 +c0df0014 +785780bf +bf0e1708 +5780ea5c +80bfc057 +a0470f8f +ff0f0000 +810205ba +a0574eec +81f02702 +41970070 +4383ce0c +070f0000 +80bf087e +d397081a +22ea0c08 +80bfc097 +178f108f +0000a087 +05baff0f +4eba8102 +a702a097 +007082f0 +0c0c5397 +80bfc08f +5cbfc607 +bfba80bf +708197a6 +bf36170c +bf86177c +78bf047c +870c7197 +090a08d1 +78bfc387 +17730a04 +0c7cbf34 +1a08d187 +7086175e +877cbf0c +0a1008d6 +08d48709 +0f0a0010 +2ba5d8ce +800495e7 +ea0422b3 +bfc49708 +d700107c +00a0bf85 +0358c017 +05d754c0 +034cc017 +c00348c0 +2f05d744 +51bb02bc +64bfc01f +23ea040a +70bfc5d7 +220cc5d7 +1f01570f +ea057a00 +c5d71480 +102270bf +001f0157 +80ea057a +ef005f05 +9260bfc4 +8210120f +c4af1880 +18c0176c +057f008f +af14c057 +00000e14 +e714c4af +c5e774c5 +02bc2f78 +01d786b7 +057a001f +e73b80ea +c5d770c5 +78c5d774 +bb02bc2f +1f01d722 +ea047a00 +d7b85f24 +22001095 +1f01d714 +ea047a00 +18c5d714 +2214c5d7 +d705d715 +c07f14c5 +ef01d770 +01926cc4 +00821032 +a5d8ce08 +7cc5e708 +d6071622 +0d1a7c08 +1ca5d8ce +800495e7 +170422df +047c10d4 +7c08d417 +7cc69700 +92005f10 +82003200 +d6870c00 +0d1a1008 +1ba5d8ce +800495e7 +df0422fc +1095d7b8 +17142200 +d6177c06 +86977810 +ce100478 +e708a5d8 +172278c5 +0092005f +00820032 +97182204 +d6970c06 +b85f1008 +06971922 +22b8df14 +18069719 +1922b95f +df1c0697 +971922b9 +00922006 +b85f0032 +b8df08ea +b9df04ea +00001a22 +d7000082 +c5d710c5 +a5d8ce0c +0495e72b +92002200 +82083200 +b8df0000 +2c0495e7 +ce0cc5d7 +2210a5d8 +32009201 +00008204 +95e7b8df +c5d72d04 +22b85f0c +32009201 +04008204 +d6970222 +d5d71008 +1f032214 +d7090a00 +042214d5 +d8ce0fea +95e71aa5 +05222e04 +92b78602 +82003200 +c4af14e0 +10c1576c +5800a57d +5774c4af +c0970cc0 +a018ce74 +00030e16 +85d7315f +c5e71474 +d706227c +c5d70cc5 +d72dd774 +7cc5d735 +01d70722 +046a011f +381f385f +80ea057a +00a1872c +1a080000 +1a381f08 +1f1dea04 +ce081a38 +ea08a198 +00a18710 +1a080000 +ea31df06 +ea05ea04 +3817b3bf +926cc4ef +82083207 +d8ce0000 +95e724a5 +22498004 +1485d708 +df092214 +0495e7ba +08226e80 +041485d7 +d8ce0922 +95e70ea5 +22748004 +10c5d708 +bb5f0922 +800495e7 +d7082283 +22141885 +e7badf09 +8a800495 +85d70822 +09220418 +95e7bb5f +22908004 +1885d708 +22092208 +10c5d70a +85020b22 +320092d1 +0ce08210 +5710c197 +28170471 +01d7060f +1a00401f +0cb4270a +ea000c00 +00441707 +0792000c +e0820832 +5f0d220c +00a18730 +ca0a0000 +a1872a80 +0a000000 +850205ba +96f82785 +41d71010 +08d1c704 +3dd70d0a +01570e22 +ea0079d7 +ea308f72 +10d5d752 +01570e22 +00109697 +87305f10 +000000a1 +47807a0a +0000a187 +05ba0a00 +27478502 +101096f8 +9f004017 +5f171a00 +a058ce03 +e230970e +9a005f00 +00374e05 +15ea0157 +58ce035f +30970da0 +005f00e2 +374e059a +8f015700 +b6bfea30 +0792005f +f0820032 +a5d8ce20 +78c5e768 +01970f22 +057a001f +17d980ea +877478c6 +1a1008d6 +0d224280 +7410d417 +74c69700 +47285f10 +000000a1 +d729aa0a +1710222d +d7b85f01 +17112205 +a1476806 +0a000000 +840205ba +95f867b9 +d2571010 +288f0408 +80ea53ea +10d61786 +10d41770 +c6970074 +285f1074 +0000a147 +80aa0a00 +222dd76e +47011710 +000000a1 +0205ba0a +f8678084 +d7107085 +05d7004d +06171122 +00a14768 +ba0a0000 +66840205 +1095f867 +08d25710 +00a14704 +ba0a0000 +52840205 +7085f8a7 +0451d710 +0a08d1c7 +047dd71c +25d7b85f +22087dd7 +1f019712 +ea057a00 +79d71680 +8f63ea00 +8fbfea28 +970cc017 +5f0c1004 +320f9200 +14f08204 +2210c5d7 +1a001f13 +22b8df09 +ce80ea14 +ba14c11f +22b95f09 +c280ea14 +2210c5d7 +ce011715 +e70ca5d8 +0f2270c5 +001f0157 +80ea057a +70c197a9 +0418c397 +080cc397 +1f14c057 +10800a08 +800a089f +0a091f35 +80ea4a80 +00a10784 +ba0a0000 +b6830205 +1094f8a7 +0450a710 +d3c711d7 +070a0008 +ea0079d7 +08d39777 +0033d700 +075d80ea +000000a1 +0205ba0a +f8a78c83 +97101094 +97000453 +80ea0432 +00a10743 +ba0a0000 +72830205 +1094f8a7 +0451d710 +0a08d1c7 +223dd70d +d701570e +72ea0079 +0008d397 +0000a107 +05ba0a00 +274b8302 +101094f8 +0470c217 +830205ea +92005f41 +8210320f +c11714f0 +10c5d714 +001f1322 +b8df091a +80ea1422 +10c5d75c +06171522 +00a0076c +ba0a0000 +0e830205 +1090f867 +0449d710 +570448a7 +08d1c711 +1f28800a +23801a30 +1a0423c7 +0cc3c70c +df061a08 +5f04ea00 +1f019700 +ea040a00 +d7395707 +57ea0079 +00007b57 +0e223dd7 +02700617 +0f92d082 +80820c32 +0cc5d704 +001f1322 +b8df081a +1cea1422 +220cc5d7 +0701d715 +000000a0 +0205ba0a +f827a082 +17101090 +01920040 +c0820432 +c7385f08 +000000a1 +5f197a0a +a058ce03 +e238970d +9a005f00 +00374e05 +388f0197 +039263ea +00820032 +92162200 +82083200 +90170000 +00920810 +00820032 +10901700 +32009204 +04808200 +0c1091d7 +180cc3d7 +001f1722 +bbdf0b7a +800495e7 +d7052297 +ce18223d +e70fa5d8 +9f800495 +01920522 +00820432 +32009200 +00008200 +00320092 +d70cf082 +3dd70cc1 +001f1322 +b8df091a +80ea1422 +223dd756 +07019715 +000000a0 +0205ba0a +f867ec81 +57101090 +09570048 +1090f8a7 +10c29710 +10c01f00 +035f170a +0ea058ce +00e23897 +059a005f +1700374e +5f15ea01 +a058ce03 +e238970d +9a005f00 +00374e05 +28170117 +08320f92 +07000082 +000000a6 +0fba0c09 +0000a607 +0a0cff00 +ea005f06 +9200df04 +82043200 +a6070000 +ff000000 +ce081a0c +ea0aa018 +0cc01705 +04320092 +07000082 +000000a6 +081a0c0a +ffa018ce +c01705ea +3200920c +08c08204 +1f14c1d7 +071a0cc1 +80ea005f +00a6074a +0c080000 +f43e801a +8a0002a3 +ea005f07 +79973580 +0473d70c +0073d704 +0873d70c +a3d8ce14 +7e170015 +b85f7814 +1fa5d8ce +10a5d8ce +2278c5e7 +78c3d719 +ea00df14 +005f0580 +10320392 +2210f082 +d701971a +04791731 +0e0f2057 +b2670957 +9200001b +8200320f +c5d70000 +0cc5d710 +00921c22 +f0820832 +971a2210 +1731d701 +20570479 +09570e0f +000cc257 +0f92005f +80820432 +1485d708 +78c5e714 +b6070622 +1a780001 +22b85f08 +d715ea14 +c5d718c5 +10c5d714 +d70cc5d7 +072278c5 +019201d7 +f0821032 +0cc19704 +1710c157 +d68714c1 +101a1008 +33a5d8ce +800495e7 +ea0822af +a1875780 +0a000000 +800205ba +96f82759 +41d71010 +08d1c704 +d8ce111a +95e712a5 +22e38004 +ea07df08 +18c5d731 +1f047dd7 +057a00c8 +d73b8002 +d72dd725 +00c81f35 +8002057a +087dd72d +79d71d22 +08d1c700 +005f591a +005f04ea +10320f92 +92000082 +5f003200 +df0ceab8 +5f08eab8 +df04eab9 +0a1e22b9 +6f636544 +6e496564 +470c7469 +74537465 +676e6972 +0b677241 +53746547 +65746174 +0d677241 +49746547 +6765746e +72417265 +65470e67 +72614374 +616e6964 +6772416c +74654711 +626d754e +664f7265 +756c6156 +530a7365 +74736275 +74757469 +65440965 +65646f63 +09646e45 +6f636544 +72416564 +74530f67 +676e6972 +6e496f54 +65676574 +74531072 +676e6972 +61436f54 +6e696472 +490f6c61 +6765746e +6f547265 +69727453 +4310676e +69647261 +546c616e +7274536f +07676e69 +766e6f43 +08747265 +6f6c6c41 +65746163 +6c6c410f +7461636f +74695765 +67615468 +7465530b +726f7453 +67615465 +6165440a +636f6c6c +0f657461 +6c616544 +61636f6c +72476574 +0970756f +4e746547 +61547765 +65520967 +6e727574 +0a676154 +696c7053 +6f6c4274 +530a6b63 +65487465 +6e457061 +65520c64 +48746573 +45706165 +4713646e +74537465 +4965726f +726f666e +6974616d +44116e6f +72637365 +55656269 +43646573 +6e696168 +6f745305 +46096572 +49646e69 +7475706e +6e69460a +74754f64 +0a747570 +646e6946 +61647055 +430b6574 +65736f6c +65727453 +530b6d61 +63656c65 +706e4974 +530c7475 +63656c65 +74754f74 +0c747570 +656c6553 +70557463 +65746164 +7465530e +6f727245 +72745372 +106d6165 +43746553 +72746e6f +74536c6f +6d616572 +706e490b +74537475 +6d616572 +74754f0c +53747570 +61657274 +72450b6d +53726f72 +61657274 +6f430d6d +6f72746e +7274536c +096d6165 +74697257 +74794265 +65520865 +79426461 +430b6574 +65727275 +7942746e +42096574 +6b636f6c +64616552 +6f6c420a +72576b63 +0a657469 +69725753 +79426574 +53096574 +64616552 +65747942 +7543530c +6e657272 +74794274 +42530a65 +6b636f6c +64616552 +6c42530b +576b636f +65746972 +7465470d +656c6946 +7366664f +530d7465 +69467465 +664f656c +74657366 +74794210 +754f7365 +61747374 +6e69646e +6c460b67 +4f687375 +75707475 +46530c74 +6873756c +7074754f +45097475 +664f646e +656c6946 +134f4902 +45746553 +726f7272 +6f666e49 +74616d72 +136e6f69 +45746547 +726f7272 +6f666e49 +74616d72 +0f6e6f69 +45746547 +726f7272 +7373654d +05656761 +6f727245 +65470c72 +74614474 +61745365 +530c706d +61447465 +74536574 +05706d61 +63756f54 +65440a68 +6574656c +656c6946 +6e65520a +46656d61 +10656c69 +73796850 +6c616369 +656c6946 +656d614e +74655313 +6b726f57 +44676e69 +63657269 +79726f74 +74654713 +6b726f57 +44676e69 +63657269 +79726f74 +4e415009 +6946534f +490b656c +4474696e +65527269 +470b6461 +69447465 +746e4572 +450a7972 +6944646e +61655272 +69460464 +4c06656c +6564616f +69420a72 +7972616e +656d6954 +7465530d +616e6942 +69547972 +4218656d +72616e69 +6d695479 +53664f65 +646e6174 +54647261 +17656d69 +616e6942 +69547972 +664f656d +74786554 +546c6175 +18656d69 +6e617453 +64726164 +656d6954 +6942664f +7972616e +656d6954 +78655417 +6c617574 +656d6954 +6942664f +7972616e +656d6954 +6d695404 +74530c65 +61646e61 +69546472 +4404656d +0b657461 +656d6954 +44646e41 +0b657461 +656d6954 +44646e41 +06657461 +6e676953 +430b6c61 +486c6c61 +6c646e61 +44137265 +616c6365 +76456572 +48746e65 +6c646e61 +52127265 +766f6d65 +65764565 +6148746e +656c646e +76450b72 +53746e65 +75746174 +65530e73 +65764574 +7453746e +73757461 +63654417 +6572616c +646e6f43 +6f697469 +6e61486e +72656c64 +6e614807 +72656c64 +7465530f +626f6c47 +74536c61 +676e6972 +7465470f +626f6c47 +74536c61 +676e6972 +74654713 +626f6c47 +74536c61 +676e6972 +656d614e +6f6c470c +536c6162 +6e697274 +534f0667 +65747942 +57534f06 +0664726f +6946534f +4203656c +490f4342 +7265746e +74657270 +69727453 +4911676e +7265746e +74657270 +6d6d6f43 +73646e61 +6d6f4307 +646e616d +6c614304 +7552036c +624f046e +49067965 +6b6f766e +74530465 +5314706f +6e4b7465 +436e776f +616d6d6f +5073646e +09687461 +75677241 +746e656d +614e0473 +5609656d +6f627265 +79746973 +65644910 +6669746e +71655279 +65726975 +65480c64 +6552706c +72697571 +50076465 +72676f72 +52066d61 +6f646e61 +65530d6d +6e615274 +536d6f64 +06646565 +646e6152 +48206d6f +79707061 +616d5820 +202d2073 +65766144 +69654b20 +4d206874 +206b7261 +6863654b +53206c69 +6e6f6d69 +6f542065 +54207962 +21766572 diff --git a/src/ROM/tuberom_32016_200.dat b/src/ROM/tuberom_32016_200.dat new file mode 100644 index 0000000..aa7d912 --- /dev/null +++ b/src/ROM/tuberom_32016_200.dat @@ -0,0 +1,8192 @@ +7f010b0e +01f0c0aa +0000007e +00000000 +00000000 +00000000 +03de0020 +00000030 +0ce60020 +0ce90020 +0cec0020 +06280020 +0cef0020 +0cf20020 +0cf50020 +0cf80020 +0cfb0020 +0d210020 +0d210020 +0d230020 +0d280020 +0d2d0020 +0d320020 +0d370020 +0d3c0020 +0d410020 +0d460020 +0d4b0020 +e0f2fdfe +07fc0103 +a17d0762 +c8570008 +4e98ce10 +d0dc0400 +ce088f05 +8f004818 +80d0a700 +00000edc +2008a37d +0412e072 +7006a574 +0d547c9a +1f001272 +74110a10 +9a7006a5 +004d547c +cf088f72 +00127417 +a718bea7 +148580de +ba800d04 +06a5742a +5c7c9a74 +a57476aa +7c9a7406 +74761554 +9a7406a5 +760d547c +7a74a81c +a898ce7d +12002376 +d840ee00 +7c1a8a0d +0904d8e7 +8284130d +0012105f +0081a8a7 +d0970012 +d400121c +d41dd40d +5fbb5c15 +06a57402 +547c9a74 +07cf76bd +9da04477 +01df1a0a +7a74a81c +76add47d +ce7807cf +ce01c8d8 +b81cb899 +000f033c +98ce0012 +088f0048 +575bbfea +7f7502b8 +1b0ec70a +081710aa +2fce085f +05d712d8 +b8577102 +0230a040 +001231bf +0000000a +00f00018 +a85c0042 +0000f9c0 +3878dd67 +6f80a4ec +005f6ddf +0200a003 +00570000 +11a0484e +085f048a +d7004097 +da170048 +da570031 +46c70031 +2d1a2900 +27004ec7 +da17271a +da570021 +46c70019 +191a1900 +0f004ec7 +1217131a +001a5700 +aabcbfea +555555aa +17aaaa55 +1a570012 +bd40e700 +d71cefbc +a8673402 +7c485f30 +677d0e4f +5fc080a8 +0e4f3c48 +bddd677d +1d5728ff +301d5720 +b581dd67 +20ade708 +3205dde7 +bcc86700 +1c0e9700 +a254b827 +088f0023 +781a0807 +1827bf02 +646e6150 +2061726f +30303233 +32562030 +2030302e +20202020 +4e34d057 +02f6a057 +bf020abf +4b200601 +0a0a0d42 +a7db8002 +dea718be +d7df1422 +08a37d0c +06a57400 +5c7c9a70 +a81c72a8 +947d7a74 +5f2876ae +18ea14d0 +1c28d05c +0adc80d0 +80d0670f +b9be02dc +02bfbe02 +d0dc0a0d +5c0edc31 +021fdc10 +101c1dbe +d79f141a +870f1a0c +efcdaba6 +061a2001 +2eea10df +3412a697 +df207856 +28d01c10 +17ce807a +079f0cd0 +02c6800a +c1809a30 +081f105f +08df090a +ea10d017 +d080020a +5f24d017 +20acef08 +000aa5d7 +0e580001 +d705d703 +573a0215 +df0042b8 +40d8ce08 +03a70707 +00284329 +45d41e1a +0da5e806 +1a09a5c4 +0f085f18 +03e01c1a +188f060a +e00379ea +a37c0543 +0f001220 +67001200 +577480d0 +003c04a2 +48a70020 +0ca82704 +5f00030e +a6972cd0 +44423d30 +14d05f38 +5c04d05f +5cdc80d0 +d0dc30d0 +29d0dc2a +dcbcdea7 +bcd86700 +80d0a7ab +0ba827a8 +2700030e +6fa880d0 +de80ce07 +d480efbc +02a37d07 +1cd4ef00 +0002a17d +d8170012 +001f7abc +e027100a +0262bcd8 +069a60bf +060a081f +028ad827 +bfea0502 +24069736 +cdaba697 +122001ef +1c21e200 +116a70a8 +7a7ca81c +adbead78 +72dde7bf +ce6a80ea +1272a818 +a81c0000 +5d806a7c +7a70a81c +a57cf988 +1405d70c +001c72a8 +4d02296a +02040657 +08065748 +06574302 +ba031c0c +0ca82705 +80d0f697 +b8170874 +7c08d07f +82eaf4a5 +06a034f9 +5f2fd43c +cc3f04c8 +80ae6708 +b8170cfd +2e03a6b4 +d07f639a +5dea9c80 +05d70032 +ad570dd7 +dd673020 +ce389d88 +9c7ea818 +6981aa03 +473cd067 +423d31a2 +391a7c44 +571c3a57 +2a571832 +10225714 +570c1a57 +ca570812 +ca570404 +ca570008 +ca572c0c +4c2f3010 +14ca6728 +02a37d20 +24ba6700 +0002a17d +1c344f2f +7d7a7ca8 +9c7ea854 +d4800a02 +a81c0a5f +d47d7a7c +0fcf7ead +1a021c78 +10be9708 +57b580ea +a03430bd +9f1e9a00 +061a0cd7 +0c30ae97 +0a2ad09c +2bd0dc10 +80aa019c +1a018c78 +1c02df04 +ce165a03 +0ed8e058 +80d9e567 +80ea3894 +1a0a007f +57361428 +482730a8 +2e1a0081 +ca7ca81c +7ea81c7d +ca78a81c +004d547d +78a81c7a +4d547dca +090f7a01 +6a1a0807 +ca78a81c +7aa85c7d +004d80ea +ca7ca81c +7ea81c7d +ca78a81c +7aaa547d +78a81c00 +aa547dca +090f017a +6a1a0807 +085c29ea +ca7ca81c +7ea81c7d +ca78a81c +7aa81c7d +ca78a81c +7aa81c7d +ea700f4c +7ca81c0a +a8147d7a +17b8577e +9a81eab8 +7a00d554 +3001d567 +ae940042 +d567007a +00423001 +427aa81c +d5540000 +d5547a00 +d5677a01 +00423002 +007aae94 +017aae94 +3002d567 +a81c0042 +7aa81c7a +a37d0042 +a81c0008 +547d7a74 +d7df76a8 +74a81c04 +ae947d7a +085f0476 +0d040eea +8f090a7f +d1071408 +a81cdc80 +147d7a74 +001c76a8 +0e946a1a +b857dc80 +d01fb817 +ef130a14 +a5d518d4 +bfad2008 +5f14d5d7 +004214d0 +2e04a6b4 +e703819a +5ffe80ad +04d5d7b8 +0008a17d +a080d07f +00f3bdea +18ce05d7 +0f010488 +001c04c9 +079c09ca +c814056a +3f050400 +b7be864a +9ad48006 +a648b786 +ef7d0a20 +010102d8 +00e50158 +02cd00ea +03390301 +06b00409 +053004ae +063a058d +05c80660 +016d06b0 +06b006b0 +010d0225 +06b006b0 +06b006b0 +06b006b0 +06b006b0 +01f70190 +012d0126 +06b006b0 +06b006b0 +06b006b0 +06b002c7 +06b006b0 +06b006b0 +06b006b0 +06b006b0 +017f00e2 +00e20164 +022e02c0 +01c60172 +57b4b902 +a65804d0 +d01c0a20 +17190a2d +80ade7b8 +5fb85ffb +08a17db8 +80d07f00 +f4a57c94 +b81708ea +0008a17d +1a2cd01c +4e004204 +3000a688 +a6b4328a +119a2c02 +fc80ade7 +b85fb85f +9880d07f +b4f4a57c +9a2c00a6 +08a67417 +e7119a06 +5ffa80ad +7fb85fb8 +7c9080d0 +0042f4a5 +44babfea +191a0da0 +7006a574 +a5547c9a +a574720a +7c9a7006 +720da554 +749ebfea +9a7006a5 +720d547c +d792bfea +6715d70d +ce010c88 +027f4898 +0e5744b9 +57b8970c +79bfeab8 +0b01a648 +7472bfea +8a0a09a6 +55b8170e +7c0e06ce +85eaf8a5 +04c8275c +0002a37d +1500ba17 +a57c04ba +02a17dfe +eab81700 +15d74385 +9703b902 +ea1063b8 +a0573bbf +00020000 +5f32bfea +d9bbea11 +ce00a074 +3c29d058 +bfea29d4 +0a081f20 +0208170a +bfeae2bb +ea125f14 +18cebbbb +ba031c08 +4a051c09 +f3a02014 +80d0f5d7 +d0179774 +b8977480 +02f2beea +1405c9be +656c6c49 +206c6167 +6e657665 +756e2074 +7265626d +0cd840ee +0dd7638a +06d8e77c +120bfafe +9416160b +085f3016 +08df08ea +095f04ea +2cd10734 +d11700ae +143f012c +beeab857 +7dbeafa8 +ce0008a1 +dc80d018 +045a0087 +00d71017 +08970dd7 +dd80d067 +5c00000e +57dc80d0 +d71897b8 +beef04d0 +ce7abeea +0a2fd648 +71beeaa0 +0a08a674 +0044238a +0444800a +804a3f0d +b70ef45f +58809ae3 +d4800eb4 +801688ae +0c3f01d4 +024abeea +200121be +276e6143 +73752074 +534f2065 +4952505f +72662056 +75206d6f +20726573 +65646f6d +02fcbd02 +6e61431c +75207427 +4f206573 +52505f53 +6f205649 +534f206e +4952505f +dbbd0256 +61432003 +2074276e +20657375 +505f534f +20564952 +75206e6f +6f6e6b6e +53206e77 +58ce4356 +bdea31d0 +000e97d8 +a7d2bdea +dea718be +7414a9bd +9a7406a5 +76a85c7c +7a74a81c +76a8147d +7a74a81c +76a8547d +1c14d05f +a9bd7a00 +1b80bd02 +63734506 +02657061 +48ce71b7 +9a000a06 +bdea93bd +0010106d +00000505 +04000505 +08000505 +04000e00 +01090105 +00000505 +20180108 +0d0d1000 +0880000d +a7808008 +dea718be +ce143dbd +081c0858 +7470800a +9a7406a5 +08a5547c +06a57476 +547c9a74 +0d04760d +d507aa80 +12ea0055 +5a140d04 +bfddd508 +d507eaa4 +9ebfd9ed +74b818ce +9a7406a5 +7605547c +100a001f +7406a574 +e5547c9a +cf767f50 +b8147507 +7406a574 +05547c9a +0a001f76 +74a81c0f +af147d7a +cf7f7650 +d05f7607 +e9bcea14 +55d4bbdd +0555d404 +d40655d4 +035f0aa5 +7406a574 +bd547c9a +7707cf76 +7a74a81c +76a8147d +0c7a001c +e714d05f +ea18bfdd +501791bc +74a81c00 +aa147d7a +008f0076 +7f0da204 +d05f711a +e300d714 +1f8f0050 +5c96bcea +d7df2bd0 +29d6940c +18bea72a +5a80dea7 +06a57414 +5c7c9a74 +101f76a9 +4d04170a +110a0d00 +7406a574 +4d547c9a +088f7600 +746e17cf +9a7406a5 +0da5547c +74a81c76 +a8147d7a +14d05f76 +9c2ad0dc +1b1a2bd0 +041cbc02 +414f4c11 +55522f44 +6964204e +6c626173 +bcea6465 +7a001c09 +d01727bc +3ab8020c +081f1a9a +d6570e0a +a6550410 +ea080001 +b8020fbc +ea11dfd7 +bb0205b8 +4e1106de +6120746f +30323320 +69203631 +6567616d +a718bea7 +14c8bbde +d714a5d4 +d735d73d +2725d72d +a57411a8 +7c9a7406 +7fc8e554 +7507cf76 +02efa57c +06a57435 +547c9a74 +a81c760d +547d7a74 +a06b76a8 +7f000000 +1c10a827 +7d7a74a8 +cf76add4 +d05f7807 +57b91714 +d7b997b9 +95bbeab9 +14ea005f +0d10e504 +a574120a +7c9a7406 +7610e554 +00c7008f +a5746c1a +7c9a7406 +760da554 +bea70012 +bbdea718 +a5741446 +7c9a7406 +7612a554 +7406a574 +0d547c9a +1a081c76 +06a57419 +547c9a74 +a81c7615 +147d7a74 +d05f76a8 +39bbea14 +1ca4bf02 +7d7a74a8 +76a858ce +1c14d05f +25bb1a08 +00fcba02 +6c69460e +6f6e2065 +6f662074 +a7646e75 +dea718be +d414e9ba +15d40ca5 +0dd41dd7 +a57403df +7c9a7406 +7fc8e554 +7507cf76 +dff9a57c +74a81c02 +add47d7a +7807cf76 +d714d05f +eab854b8 +bea7d7ba +badea718 +a5d414ae +d72dd716 +d41dd725 +270dd415 +a5740fa8 +7c9a7406 +7fc8e554 +7507cf76 +27f1a57c +a81c0ea8 +d47d7a74 +07cf76ad +ceb81478 +b8d7b898 +b957b917 +0d4a089c +09aa0a1c +00bc201f +1c00204e +7d7a74a8 +76a858ce +1c14d05f +75ba7a00 +fe4cba02 +646e450b +20666f20 +656c6966 +a718bea7 +143cbade +7406a574 +a5547c9a +a574760e +7c9a7406 +1c761554 +7d7a74a8 +ea76a814 +bea7bcbf +badea718 +a5741416 +7c9a7406 +7610a554 +7406a574 +15547c9a +06a57476 +547c9a74 +a81c760d +147d7a74 +d05f76a8 +0dbaea14 +02002502 +1f020422 +0c1c0208 +02101902 +13021816 +2010021c +02240d02 +b817280a +0302bf0f +ce05d714 +00048818 +0090e5d7 +cdd9ce00 +06c85d02 +08048dc3 +3208c817 +02004208 +5442412d +50462802 +49230255 +1e024c4c +02435653 +5a564419 +4c461402 +420f0247 +0a025450 +02435254 +444e5505 +1203b402 +2a0a0a0d +45202a2a +70656378 +6e6f6974 +b8572820 +b30211df +e6b30241 +61202909 +43502074 +b857203a +0218a8a7 +d2b30212 +2a2a2007 +0a0a0d2a +b6ea12df +0f0dd708 +b8502e16 +30a04004 +7a390d04 +020b8c04 +101ffdb2 +b8576b1a +a5d70012 +2000000b +4205dde7 +1cd4ef00 +2a0115e2 +7e00a5d7 +d5e7e820 +085f5c81 +07e2b8a7 +8af8a57c +ea1f0206 +540b0262 +105f7ea0 +57ea06e2 +5c81d067 +e880a8a7 +02e21fe2 +001204e2 +8002205f +042d0a4c +1e1a4705 +01d42802 +05042402 +04134a20 +800a533d +553d0440 +043e800a +380a4f3d +5c81d067 +08e21897 +0012408a +d4e018ce +05045c81 +8f0d0a0d +d808ee20 +08058a0b +001220a0 +6602617a +0a200504 +0d05047b +305f0012 +30df04ea +285f6e02 +1ad808ee +08ee0b9a +148a16d8 +4e0aa040 +4304a157 +bbbf0209 +303968ea +05044146 +070a4a20 +0100002d +0215ba00 +420dd0b2 +61206461 +65726464 +0a0d7373 +bf020012 +02150aac +450db8b2 +73656378 +72612073 +0a0d7367 +20e20012 +0002a17d +d40aa198 +d5b85c35 +d70001a5 +0000422d +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 diff --git a/src/ROM/tuberom_32016_tst.dat b/src/ROM/tuberom_32016_tst.dat new file mode 100644 index 0000000..c76aa4c --- /dev/null +++ b/src/ROM/tuberom_32016_tst.dat @@ -0,0 +1,8192 @@ +000D20EA +6C696146 +65646F63 +12203A20 +65542000 +20737473 +72726F63 +2E746365 +A4EF385F +00000100 +A01738DD +AAFFFFFF +07CCA028 +FFFFFFA0 +799C1A88 +A017395D +5555FFFF +3333A029 +FFFFA007 +9C1A1111 +1739DD64 +AAAAAAA0 +CCA02BAA +07CCCCCC +888888A0 +4D9C1A88 +A0173A5D +AAFFFFFF +07CCA008 +FFFFFFA0 +399C1A22 +A0173ADD +5555FFFF +3333A009 +FFFFA007 +9C1A4444 +173B5D24 +AAAAAAA0 +CCA00BAA +07CCCCCC +22222205 +0D9C1A22 +A0173BDD +CC000000 +07AAA018 +000000A0 +F99B1AEE +0800A1D5 +0000A017 +A0193333 +A0075555 +77770000 +D5E29B1A +170900A1 +A55AC3A0 +A5A01B3C +075AC33C +E77EE7A0 +C99B1A7E +0A00A1D5 +FFFFA017 +A038AAFF +FFA007CC +1A66FFFF +A1D5B39B +A0170B00 +5555FFFF +3333A039 +FFFFA007 +9B1A6666 +00A1D59C +ACA0170C +3BCA3553 +5335CAA0 +66A007AC +1A666666 +A1D5839B +A0570D00 +55555555 +344E005F +00A00708 +1AAA0000 +A1D56B9B +005F0E00 +0708354E +AA0000A0 +599B1AAA +0F00A1D5 +374E005F +AAA00708 +1AAAAAAA +A1D5479B +A0571000 +AAAAAAAA +344E005F +00A00708 +1A550000 +A1D52F9B +005F1100 +0708354E +550000A0 +1D9B1A55 +1200A1D5 +374E005F +55A00708 +1A555555 +A1D50B9B +085F1300 +244E07DF +FFA00708 +1A01FFFF +A1D5F79A +07DF1400 +0708254E +00FFFFA0 +E59A1A01 +1500A1D5 +274E07DF +1A009F08 +A1D5D79A +0FDF1600 +244E005F +00A00708 +1AFE0000 +A1D5C39A +005F1700 +0708254E +FF0000A0 +B19A1AFE +1800A1D5 +274E005F +1A071F08 +A1D5A39A +A17C1900 +40A37CFF +AAAAA017 +003CAAAA +AAAAA007 +9A1A01AA +00A1D588 +40A37C1A +AAAAA017 +003DAAAA +AAAAA007 +9A1A0100 +00A1D570 +40A37C1B +AAAAA017 +003FAAAA +9A1A009F +81D8A75C +00A1D590 +1FA0541C +3C668102 +00500400 +8C469A1A +9C108F0F +D56F1A0F +541D00A1 +81021FA0 +0400BC4C +9A1A0050 +8F0F8C2C +1A0F9C10 +00A1D56F +1FA0541E +3C328102 +00500401 +8C129A1A +9C108F0F +D56F1A0F +541F00A1 +81021FA0 +0401BC18 +991A0050 +8F0F8CF8 +1A0F9C10 +00A1D56F +1FA05420 +3CFE8002 +00500402 +8CDE991A +9C108F0F +D56F1A0F +542100A1 +80021FA0 +0402BCE4 +991A0050 +8F0F8CC4 +1A0F9C10 +00A1D56F +1FA05422 +3CCA8002 +00500403 +8CAA991A +9C108F0F +D56F1A0F +542300A1 +80021FA0 +0403BCB0 +991A0050 +8F0F8C90 +1A0F9C10 +00A1D56F +1FA05424 +3C968002 +00500404 +8C76991A +9C108F0F +D56F1A0F +542500A1 +80021FA0 +0404BC7C +991A0050 +8F0F8C5C +1A0F9C10 +00A1D56F +1FA05426 +3C628002 +00500405 +8C42991A +9C108F0F +D56F1A0F +542700A1 +80021FA0 +0405BC48 +991A0050 +8F0F8C28 +1A0F9C10 +00A1D56F +1FA05428 +063C2E02 +1A005004 +0F8C0F99 +0F9C108F +A1D5701A +A0542900 +BC15021F +00500406 +8CF6981A +9C108F0F +EA701A0F +08D4E281 +CE01A0E8 +CE20090C +CE4020C8 +CE42090C +7CA220C8 +1B7CFFA1 +12AAA014 +01010100 +01010101 +00000001 +00000000 +01010100 +01010101 +00000001 +00000000 +00000000 +00000000 +01010100 +01010101 +00000001 +00000000 +01010100 +01010101 +01000101 +01000100 +01000100 +01000100 +01000100 +01000100 +01000100 +01000100 +00010000 +00010001 +00010001 +00010001 +00010001 +00010001 +00010001 +00010001 +00010101 +00010100 +00010100 +00010100 +00010100 +00010100 +00010100 +00010100 +01000000 +01000001 +01000001 +01000001 +01000001 +01000001 +01000001 +01000001 +01010101 +01010101 +01010101 +01010101 +00000001 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +01010100 +01010101 +01010101 +01010101 +01010101 +00000001 +01010100 +00000001 +01010100 +00000001 +01010100 +00000001 +00000000 +01010100 +00000001 +01010100 +00000001 +01010100 +00000001 +01010100 +00000001 +00000000 +01000000 +01000001 +00000001 +00000000 +01000000 +01000001 +01010101 +01010101 +00010101 +00010100 +01010100 +01010101 +00010101 +00010100 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +01010100 +01010101 +01010101 +01010101 +01010101 +01010101 +01010101 +01010101 +00000001 +00000000 +00A1D500 +55A0172A +4E555555 +0701A014 +555555A0 +F5961AAA +2B00A1D5 +5555A017 +154E5555 +A00701A0 +AAAA5555 +D5DE961A +172C00A1 +555555A0 +A0174E55 +AAA00701 +1AAAAAAA +A1D5C796 +085F2D00 +174E00DF +D9F00708 +B5961A33 +0D04088C +D56F1A20 +542E00A1 +D8A7E1A0 +80A0171E +4E000000 +50070817 +95961A00 +08CC120F +8780EA6F +80000000 +00000001 +00000002 +00000004 +00000008 +00000010 +00000020 +00000040 +00000080 +00000100 +00000200 +00000400 +00000800 +00001000 +00002000 +00004000 +00008000 +00010000 +00020000 +00040000 +00080000 +00100000 +00200000 +00400000 +00800000 +01000000 +02000000 +04000000 +08000000 +10000000 +20000000 +40000000 +80000000 +2F00A1D5 +AAAAA017 +044EAAAA +A007FBA0 +FDAAAAAA +D5F2951A +173000A1 +AAAAAAA0 +A0054EAA +AAA007FB +1A55FDAA +A1D5DB95 +A0173100 +AAAAAAAA +FBA0074E +55FDA007 +951A5555 +00A1D5C4 +55A01732 +4E555555 +07FBA004 +555555A0 +AD951A02 +3300A1D5 +5555A017 +054E5555 +A007FBA0 +AA025555 +D596951A +173400A1 +555555A0 +A0074E55 +02A007FB +1AAAAAAA +A1D57F95 +085F3500 +074E07DF +D9F00708 +6D951A2F +A044088C +D56F1A20 +543600A1 +D8A7E1A0 +80A0171A +4E000000 +50070807 +4D951A00 +08CC120F +8380EA6F +FFFFFFFF +FFFFFFFE +FFFFFFFC +FFFFFFF8 +FFFFFFF0 +FFFFFFE0 +FFFFFFC0 +FFFFFF80 +FFFFFF00 +FFFFFE00 +FFFFFC00 +FFFFF800 +FFFFF000 +FFFFE000 +FFFFC000 +FFFF8000 +FFFF0000 +FFFE0000 +FFFC0000 +FFF80000 +FFF00000 +FFE00000 +FFC00000 +FF800000 +FF000000 +FE000000 +FC000000 +F8000000 +F0000000 +E0000000 +C0000000 +80000000 +3700A1D5 +AAAAA017 +004EAAAA +A00701A0 +55AAAAAA +D5AE941A +173800A1 +AAAAAAA0 +A0014EAA +AAA00701 +1A5555AA +A1D59794 +A0173900 +AAAAAAAA +01A0034E +5555A007 +941A5555 +00A1D580 +17085F3A +000080A0 +08034E00 +BDD9F007 +69941AE4 +A044088C +D56A1A20 +543B00A1 +D8A7E1A0 +A017CEBD +00000040 +0708034E +941A0050 +CC120F48 +A1D56F08 +A17C3C00 +01A37CFF +FFFFA017 +3C4E78FF +A00710A0 +89FFFFFF +D526941A +173D00A1 +54FFFFA0 +A03D4E32 +A0079963 +3118FFFF +D50E941A +173E00A1 +563012A0 +A03F4E78 +20838587 +1600A007 +931A9939 +00A1D5F4 +FFA0173F +4E88FFFF +0722A02C +FFFFFFA0 +DD931A65 +4000A1D5 +FFFFA017 +2D4E3412 +077856A0 +55FFFFA0 +C5931A56 +4100A1D5 +7698A017 +2F4E3254 +888888A0 +09A00788 +1A436587 +A1D5AB93 +A0174200 +00FF5555 +14CE0FDF +55A00708 +1AFF0055 +A1D59393 +A0174300 +00FFFFFF +070818CE +000000A0 +7D931AFF +4400A1D5 +FFFFA017 +19CE0000 +00A00708 +1AFFFF00 +A1D56793 +A0174500 +00FF5555 +070810CE +FF5555A0 +51931AFF +4600A1D5 +AAAAA017 +1CCE00AA +1A079F08 +A1D53F93 +A0174700 +0000AAAA +9F081DCE +2D931A07 +4800A1D5 +A017085F +FFFF5555 +070810CE +005555A0 +15931A00 +4900A1D5 +AAAAA017 +1CCEFFAA +1A001F08 +A1D50393 +A0174A00 +FFFFAAAA +1F081DCE +F1921A00 +F800A57D +5400C827 +020F3EA0 +CC7C405F +D8277B0F +4654EE82 +40CE0000 +01010146 +034640CE +40CE0203 +03060646 +0A4640CE +40CE040A +050F0F46 +154640CE +40CE0615 +071C1C46 +244640CE +40CE0824 +092D2D46 +374640CE +40CE0A37 +80428046 +40CE0B42 +804E8046 +40CE0C4E +805B8046 +40CE0D5B +80698046 +40CE0E69 +80788046 +46550F78 +88808880 +804641CE +028A808A +804641CE +048E808E +804641CE +06948094 +804641CE +089C809C +804641CE +0AA680A6 +804641CE +0CB280B2 +804641CE +0EC080C0 +D0804657 +43CED080 +80D48046 +43CE04D4 +80DC8046 +43CE08DC +80E88046 +A1D50CE8 +08DF4B00 +0400C827 +921A000A +8F088C04 +00A04500 +D5721AF9 +274C00A1 +CE0982D8 +01014644 +E9911A01 +034644CE +911A0203 +4644CEE0 +1A030606 +44CED791 +040A0A46 +CECE911A +0F0F4644 +C5911A05 +154644CE +911A0615 +4644CEBC +1A071C1C +44CEB391 +08242446 +CEAA911A +2D2D4644 +A1911A09 +374644CE +911A0A37 +4644CE98 +42804280 +8D911A0B +804644CE +0C4E804E +CE82911A +5B804644 +1A0D5B80 +44CE7791 +80698046 +911A0E69 +4644CE6C +78807880 +61911A0F +804645CE +028A808A +CE56911A +8E804645 +1A048E80 +45CE4B91 +80948046 +911A0694 +4645CE40 +9C809C80 +35911A08 +804645CE +0AA680A6 +CE2A911A +B2804645 +1A0CB280 +45CE1F91 +80C08046 +911A0EC0 +4647CE14 +D480D480 +09911A04 +804647CE +08DC80DC +CEFE901A +E8804647 +1A0CE880 +44CEF390 +01000146 +CEEA900A +02034644 +E1900A02 +064644CE +900A0305 +4644CED8 +0A04090A +44CECF90 +050E0F46 +CEC6900A +14154644 +BD900A06 +1C4644CE +900A071B +4644CEB4 +0A082324 +44CEAB90 +092C2D46 +CEA2900A +36374644 +99900A0A +804644CE +0B418042 +CE8E900A +4E804644 +0A0C4D80 +44CE8390 +805B8046 +900A0D5A +4644CE78 +68806980 +6D900A0E +804644CE +0F798078 +CE62900A +8A804645 +0A028980 +45CE5790 +808E8046 +900A048D +4645CE4C +93809480 +41900A06 +804645CE +089B809C +CE36900A +A6804645 +0A0AA580 +45CE2B90 +80B28046 +900A0CB1 +4645CE20 +BF80C080 +15900A0E +804647CE +04D380D4 +CE0A900A +DC804647 +0A08DD80 +47CEFF8F +80E88046 +8F0A0CE7 +FFA57DF4 +FB80EA08 +04030201 +08070605 +0C0B0A09 +100F0E0D +14131211 +18171615 +1C1B1A19 +201F1E1D +24232221 +28272625 +2C2B2A29 +302F2E2D +34333231 +38373635 +3C3B3A39 +403F3E3D +44434241 +48474645 +4C4B4A49 +504F4E4D +54535251 +58575655 +5C5B5A59 +605F5E5D +64636261 +68676665 +6C6B6A69 +706F6E6D +74737271 +78777675 +7C7B7A79 +807F7E7D +84838281 +88878685 +8C8B8A89 +908F8E8D +94939291 +98979695 +9C9B9A99 +A09F9E9D +A4A3A2A1 +A8A7A6A5 +ACABAAA9 +B0AFAEAD +B4B3B2B1 +B8B7B6B5 +BCBBBAB9 +C0BFBEBD +C4C3C2C1 +C8C7C6C5 +CCCBCAC9 +D0CFCECD +D4D3D2D1 +D8D7D6D5 +DCDBDAD9 +E0DFDEDD +E4E3E2E1 +E8E7E6E5 +ECEBEAE9 +F0EFEEED +F4F3F2F1 +F8F7F6F5 +4D00A1D5 +1701A37C +FFFFFFA0 +C3A00068 +FFFFA007 +8E1A2BFF +00A1D5E0 +DAA0104E +FFFFA007 +8E1A06FF +00A1D5D0 +FFA0174F +017798FF +075476A0 +0EFFFFA0 +B98E1ACB +5000A1D5 +4444A011 +FFFFA007 +8E1A1053 +00A1D5A8 +01A37C51 +87A9A017 +A0034465 +D3F2E1B0 +695AA007 +8E1A1758 +00A1D58C +12A01352 +07785634 +AE9D6CA0 +798E1A90 +5300A1D5 +1701A17C +FFFFFFA0 +23A00067 +FFFFA007 +8E1A8AFF +00A1D560 +33A01054 +FFFFA007 +8E1ABDFF +00A1D550 +FFA01755 +017698FF +073412A0 +AAFFFFA0 +398E1AAA +5600A1D5 +4444A011 +FFFFA007 +8E1AEEEE +00A1D528 +01A17C57 +3412A017 +A0037856 +89674523 +7935A007 +8E1A01BE +00A1D50C +12A01358 +07785634 +14AE47A0 +F98D1A79 +5900A1D5 +1701A37C +FFFFFFA0 +C3A02068 +FFFFA007 +8D1AA5FF +00A1D5E0 +DAA0305A +FFFFA007 +8D1ACAFF +00A1D5D0 +FFA0175B +217778FF +075496A0 +E2FFFFA0 +B98D1A23 +5C00A1D5 +4444A031 +FFFFA007 +8D1ADE9D +00A1D5A8 +01A37C5D +87A9A017 +A0234465 +D3F2E1B0 +A5F8A007 +8D1A7172 +00A1D58C +12A0335E +07785634 +1B71E6A0 +798D1AF8 +5F00A1D5 +1701A17C +FFFFFFA0 +23A02067 +FFFFA007 +8D1A44FF +00A1D560 +33A03060 +FFFFA007 +8D1A11FF +00A1D550 +FFA01761 +217698FF +073412A0 +86FFFFA0 +398D1A42 +6200A1D5 +4444A031 +FFFFA007 +8D1AFE41 +00A1D528 +01A17C63 +3432A017 +A0237856 +89674513 +EE1EA007 +8D1AEFEE +00A1D50C +12A03364 +07785634 +98BA0CA0 +F98C1A77 +6500A1D5 +A05707DF +55FFFFFF +0708204E +FFFFFFA0 +E18C1AAB +6600A1D5 +304E07DF +FFA00708 +1A55FFFF +A1D5CF8C +07DF6700 +FFFFA057 +204EB6FF +FFA00708 +1A4AFFFF +A1D5B78C +07DF6800 +0708304E +FFFFFFA0 +A58C1A4A +6900A1D5 +A05707DF +3412FFFF +0708214E +EDFFFFA0 +8D8C1ACC +6A00A1D5 +314E07DF +FFA00708 +1A3412FF +A1D57B8C +07DF6B00 +FFFFA057 +214E7698 +FFA00708 +1A8A67FF +A1D5638C +07DF6C00 +0708314E +67FFFFA0 +518C1A8A +6D00A1D5 +A05707DF +78563412 +0708234E +A9CBEDA0 +398C1A88 +6E00A1D5 +334E07DF +12A00708 +1A785634 +A1D5278C +07DF6F00 +CBEDA057 +234E88A9 +12A00708 +1A785634 +A1D50F8C +07DF7000 +0708334E +563412A0 +FD8B1A78 +7100A1D5 +FFFFA017 +20CE05FF +A0070CA0 +3CFFFFFF +D5E68B1A +177200A1 +00FFFFA0 +A021CE15 +A0077800 +D809FFFF +D5CE8B1A +177300A1 +FF0000A0 +A023CE05 +B0040000 +AB04A007 +8B1A7067 +00A1D5B4 +00A01774 +CEF00100 +0703A030 +010000A0 +9D8B1AFB +7500A1D5 +0100A017 +31CE00FC +070500A0 +FF0100A0 +858B1A34 +7600A1D5 +80FFA017 +33CE0000 +000000A0 +FFA00707 +1ADCB6ED +A1D56B8B +A0177700 +F0010000 +03A034CE +0000A007 +8B1AFF01 +00A1D554 +00A01778 +CE00FC01 +0500A035 +0100A007 +8B1AFCFF +00A1D53C +FFA01779 +CE010080 +0000A037 +069F0700 +D5268B1A +177A00A1 +010000A0 +A03CCEF0 +00A00703 +1AFA0100 +A1D50F8B +A0177B00 +00FC0100 +00A03DCE +00A00705 +1A33FF01 +A1D5F78A +A0177C00 +000080FF +00A03FCE +07070000 +B6EDFFA0 +DD8A1ADB +7D00A1D5 +0000A017 +38CEF001 +A00703A0 +02010000 +D5C68A1A +177E00A1 +FC0100A0 +A039CE00 +A0070500 +01000100 +D5AE8A1A +177F00A1 +0080FFA0 +A03BCE01 +07000000 +8A1A021F +00A1D598 +FFA01780 +DF14FFFF +A024CE0F +FFA0070F +1A2CFFFF +A0477F8A +01FFFFFF +D5768A1A +178100A1 +01FFFFA0 +CE0FDF23 +9001A025 +FFFFA007 +8A1AB0C6 +FFA0475C +1A0100FF +A1D5538A +A0178200 +45230100 +27CE0FDF +0D0300A0 +78A00740 +1A4052E2 +099F378A +D5328A1A +CE8300A1 +0100A02F +001F4523 +47228A1A +0D0300A0 +198A1A40 +8400A1D5 +FFFFA017 +A057B0C6 +0100FFFF +01A02DCE +FFA00723 +1A0000FF +A047FB89 +9001FFFF +D5F2891A +178500A1 +FFFFFFA0 +FFA0572C +CE01FFFF +0714A02C +FFFFFFA0 +D5891A00 +FFFFA047 +891A0FFF +00A1D5CC +00A01786 +34000002 +899A11A0 +00A1D5BC +00A03587 +B1898A10 +FFFFC867 +485CF0D8 +2E2200C0 +8800A1D5 +0100A277 +8A007111 +495C9789 +2E2200C0 +8900A1D5 +0100A277 +9A007111 +A0178389 +01010100 +8A00A1D5 +4E00485C +8A000258 +491C6F89 +69891A00 +8B00A1D5 +0002584E +D55E899A +5C8C00A1 +594E2048 +898A0002 +20491C50 +D54A891A +5C8D00A1 +2000C048 +025B4E20 +39898A00 +00C0491C +891A2020 +00A1D530 +02484E8E +25899A00 +1A00481C +A1D51F89 +484E8F00 +898A0002 +00A1D514 +02494E90 +09899A00 +1A20481C +A1D50389 +4B4E9100 +889A0002 +C0481CF8 +1A202000 +015CEF88 +9200A1D5 +00025C4E +1CE2888A +881A004A +00A1D5DC +025C4E93 +D1889A00 +9400A1D5 +00025D4E +1CC6888A +881A204A +00A1D5C0 +025F4E95 +B5888A00 +00C04A1C +881A2020 +00A1D5AC +024C4E96 +A1889A00 +1A00481C +A1D59B88 +4C4E9700 +888A0002 +00A1D590 +024D4E98 +85889A00 +1A20481C +A1D57F88 +4F4E9900 +889A0002 +C0481C74 +1A202000 +A1D56B88 +A0179A00 +01010100 +00A0384E +075A889A +010100A0 +51881A00 +01A0384E +074A888A +010100A0 +41881A02 +00A0394E +39889A08 +0100A007 +881A0200 +A03B4E30 +10000000 +1F26889A +21881A01 +9B00A1D5 +0000A017 +A0578000 +01FFFFFF +8A00446E +A1D50B88 +A0479C00 +07FFFFFF +D5FE871A +179D00A1 +00FFFFA0 +00456E00 +D5EE879A +479E00A1 +FFFFFFA0 +E1871A00 +9F00A1D5 +0010A017 +476E0000 +D1878A00 +FFFFA047 +871A1CFF +00A1D5C8 +01A657A0 +7C0C38E0 +0CCE07DF +07237CC8 +FFFFFFA0 +AD871A06 +0DCE07DF +07447DC8 +00FFFFA0 +9D871A0E +0FCE07DF +07867EC8 +000000A0 +8D871A1E +A100A1D5 +177CCFDF +FFFFFFA0 +0648CE0A +A647247C +D5FFFFFF +71871A7C +FFFFA017 +49CE12FF +47457D06 +4BFFFFA6 +871A7CD5 +FFA0175C +CE44FEFF +887E064B +4FE4A647 +1A7CD54B +A1D54787 +A657A200 +0C38E001 +DF07DF7C +C8082E08 +A007047C +06FFFFFF +DF2A871A +2E095F07 +057DC809 +FFFFA007 +871A0E00 +5F07DF18 +C80B2E0A +A007077E +1E000000 +D506871A +DFA300A1 +A0177CCF +0AFFFFFF +48AE08DF +47057C06 +FFFFFFA6 +861A7CD5 +FFA017E8 +5F12FFFF +0649AE09 +A647067D +D54BFFFF +D1861A7C +FFFFA017 +0A5F44FE +7E064BAE +E4A64709 +7CD54B4F +D5BA861A +DFA400A1 +6E0BDF07 +A77CC80B +974E7CC8 +138F03A0 +861A1007 +00A1D5A0 +FFA017A5 +EE23FFFF +6B80D800 +078E868A +000000A0 +85861A13 +EE0FA054 +5780D840 +D57A869A +17A600A1 +12FFFFA0 +D801EE34 +868A4780 +00A00768 +1A330200 +A0555F86 +41EE0120 +869A32D8 +00A1D554 +22A017A7 +EE554433 +8A25D803 +A0074386 +15141312 +573A861A +000030A0 +D843EE02 +2D869A0F +104610EA +10012000 +30000001 +10203040 +A800A1D5 +A05702DF +07FFFFFF +FFFFA097 +842E13FF +00A00708 +1A3B0000 +A1D5FF85 +02DFA900 +FFFFA057 +A0973000 +2301FFFF +0708852E +020000A0 +E1851A18 +AA00A1D5 +A05702DF +44230100 +0200A097 +872E5634 +00A00708 +1AAFE407 +0FDFC385 +2FDF1FDF +A0173FDF +01020304 +0708A097 +A1170506 +090A0B0C +0F10A197 +55620D0E +17DF07DF +37DF27DF +A1C75572 +0D0E0F10 +0000A1D7 +851AAB00 +1A379F88 +A1478385 +090A0B0C +9F7A851A +75851A27 +0708A0C7 +851A0506 +1A179F6C +A0476785 +01020304 +9F5E851A +59851A07 +0F10A1D7 +AA820D0E +10A60708 +680D0E0F +0000A1D7 +851AAC00 +0CA60740 +6C090A0B +4736851A +060708A6 +851A0805 +04A6472C +0C010203 +9222851A +00A1D5F0 +04A007AD +1A010203 +A0471385 +05060708 +870A851A +0A0B0CA0 +01851A09 +0F10A0C7 +841A0D0E +00A1D5F8 +7C015FAE +011FD8E7 +011000A0 +012000A0 +014000A0 +078000A0 +000000A0 +D5841AC2 +080406EA +A1D5100C +015FAF00 +1FD8EF7D +0B00A001 +2100A001 +5800A001 +C700A001 +0000A007 +841A2101 +040AEAAC +0C000800 +D5001000 +5FB000A1 +D8F77F01 +00A00327 +030A0000 +000000A0 +00A00364 +03E80300 +270000A0 +00A00710 +1AFA2A00 +12EA7784 +00000004 +0000000A +00000010 +00000016 +B100A1D5 +D8270FDF +47067F14 +FFFFFFA0 +51841A05 +7582D827 +0ADC027F +82EA0012 +A00F3E6B +A8010000 +B200A1D5 +0700373E +010000A0 +2D841AA8 +0F3E005F +10A01400 +7800A055 +0000A097 +043EC307 +08453E00 +BE10873E +91BE0041 +08B1BE00 +3E00A1BE +2F3E10E7 +00A0C711 +1A724100 +A107F783 +71410000 +BEEE831A +35BE10D5 +19653E19 +B300A1D5 +8EBE2D05 +3EDA831A +A18521AD +831A7141 +00A1D5D0 +A005BEB4 +000000BE +3F3E005F +0075BE00 +7D3E0FDF +1A079F08 +A047B383 +0000FFFF +D5AA831A +BEB500A1 +0943A005 +55FE0000 +3E07DF00 +A0070824 +07FFFFFF +D58E831A +BEB600A1 +A03FA005 +45BE0000 +004040A0 +0811FE00 +07002C3E +FFFFFFA0 +6D831A0A +41A009BE +1A000020 +A1D56383 +85BEB700 +00B040A0 +088DFE00 +07003C3E +FFFFFFA0 +49831A1A +410509BE +1A0000D4 +A1D53F83 +89FEB800 +05DB3E08 +07B8233E +000000A0 +29831A55 +B900A1D5 +3400373E +839A10A0 +00373E1C +0000A02B +0F3EFFFF +65A01400 +E504A055 +0000A097 +003EA24D +08413E00 +BE10833E +90BE0040 +08B0BE00 +3E00A0BE +2B3E10E3 +00A1D511 +00A0C7BA +1A740B04 +A107DB82 +730B0400 +BED2821A +7F40A0D4 +00000078 +34BE0000 +19613E19 +BB00A1D5 +08FEA145 +3EB6821A +A18521A9 +821AF701 +00A1D5AC +A004BEBC +0000C0BF +00000000 +3B3E005F +0074BE00 +793E0FDF +1A079F08 +A0478B82 +0000FFFF +D582821A +BEBD00A1 +9540A004 +00000068 +54FE0000 +3E07DF00 +A0070820 +0AFFFFFF +D562821A +BEBE00A1 +F43FA004 +00000000 +44BE0000 +001440A0 +00000000 +0810FE00 +0700283E +FFFFFFA0 +39821A28 +40A008BE +00000044 +1A000000 +A1D52B82 +84BEBF00 +001640A0 +00000000 +088CFE00 +0700383E +FFFFFFA0 +0D821A43 +400508BE +0000E050 +1A000000 +A1D5FF81 +88FEC000 +05D63E08 +07B8273E +010000A0 +E9811A57 +C100A1D5 +3400373E +819A10A0 +01A57DDC +00C82700 +0F40A054 +7C405F02 +D57B0FCC +17C200A1 +000000A0 +B1D86713 +00C8A7CF +8500000E +7F1300A2 +D5A7811A +14C300A1 +010E0BA0 +00A28700 +7E282900 +D593811A +DCC400A1 +00030E03 +4445A287 +1A7C4243 +501F8081 +7A811A00 +C500A1D5 +FC80C8A7 +88B1D827 +F4804067 +0000A017 +030E0D00 +C8A28701 +04C5C6C7 +1F57811A +811A0050 +00A1D551 +09A014C6 +8701010E +00B1B2A2 +811A0000 +00A1D53D +0FA014C7 +8501000E +0000A1A2 +D52B811A +A7C800A1 +D86700C8 +D8E73AB1 +025F0981 +4700800E +253647A6 +811A0014 +00A1D50D +04C867C9 +1CB1D827 +170440A7 +000000A0 +00040E14 +1FF3801A +EE801A00 +CA00A1D5 +0A52604E +0CA0140A +0A00050E +039FDC80 +D5D7801A +54CB00A1 +5F000052 +00070E02 +1FC7801A +C2801A00 +CC00A1D5 +A705C867 +D8E70FC8 +02DCA180 +1A00840E +001FAC80 +D5A7801A +17CD00A1 +000000A0 +00C86720 +FFFFA117 +0C0E0DFF +8E809A06 +870CC8A7 +86801A08 +0000A007 +801A1400 +00A1D57D +00A017CE +67320000 +175080C8 +00FFFFA1 +020D0E00 +A763809A +87A880C8 +5A801A08 +801A031F +00A1D555 +97005FCF +010F0E08 +8747808A +42801A08 +D000A1D5 +0000A017 +D8670A00 +7C08D721 +8C0E20A3 +632A8A00 +00A04718 +1A0A0000 +1A001F20 +01A57D1C +FF0EEA00 +47362514 +12111000 +17001413 +A3DDE738 +7C00EA6C +A57DF8A5 +381708FF +50A3DDE7 +000000EA +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 diff --git a/src/m32632/ADDR_UNIT.v b/src/m32632/ADDR_UNIT.v new file mode 100644 index 0000000..f3f1acd --- /dev/null +++ b/src/m32632/ADDR_UNIT.v @@ -0,0 +1,354 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: ADDR_UNIT.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 7 October 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// ADDR_UNIT generates data access addresses and controls data cache operation +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module ADDR_UNIT ( BCLK, BRESET, READ, WRITE, LDEA, NEWACC, CLRMSW, POST, DISP_OK, FULLACC, SRC2SEL, INDEX, ASIZE, SRC1, SRC2, BWD, + DISP, PC_ARCHI, PC_ICACHE, IO_READY, ACC_STAT, MMU_UPDATE, IC_TEX, ABO_STAT, ADIVAR, RWVAL_1, OP_RMW, PHASE_17, + NO_TRAP, FPU_TRAP, READ_OUT, WRITE_OUT, ZTEST, RMW, VADR, ADDR, SIZE, PACKET, ACC_DONE, ABORT, REG_OUT, BITSEL, + QWATWO ); + + input BCLK,BRESET; + input READ,WRITE,LDEA; + input NEWACC; + input CLRMSW,POST,FULLACC; + input [1:0] SRC2SEL; + input [3:0] INDEX; + input [1:0] ASIZE; + input [31:0] SRC1,SRC2; + input [1:0] BWD; + input [31:0] DISP; + input [31:0] PC_ARCHI,PC_ICACHE; + input DISP_OK; + input IO_READY; + input [5:0] ACC_STAT; // Feedback from data cache about the running access + input [1:0] MMU_UPDATE; + input [2:0] IC_TEX; + input [1:0] ABO_STAT; + input ADIVAR; + input RWVAL_1; // special access for RDVAL + WRVAL + input OP_RMW; + input PHASE_17; + input NO_TRAP; + input FPU_TRAP; + + output READ_OUT,WRITE_OUT,ZTEST,RMW; + output [31:0] VADR; + output [31:0] ADDR; + output [1:0] SIZE; + output [3:0] PACKET; + output ACC_DONE; + output ABORT; + output REG_OUT; + output [2:0] BITSEL; + output reg QWATWO; + + reg [31:0] VADR; + reg READ_OUT,write_reg,ZTEST,RMW; + reg [1:0] SIZE; + reg [3:0] PACKET; + reg [2:0] BITSEL; + reg [31:0] source2; + reg [31:0] index_val; + reg [31:0] vadr_reg; + reg [31:0] ea_reg; + reg [31:0] tos_offset; + reg [31:0] icache_adr; + reg [31:0] sign_ext_src1; + reg [31:12] pg_areg; + reg reg_out_i,next_reg; + reg ld_ea_reg; + reg acc_run,acc_ende,acc_step; + reg qwa_flag; + reg no_done; + reg frueh_ok; + reg io_rdy; + reg ABORT; + reg [1:0] tex_feld; + reg [2:0] u_ddt; + reg pg_op; + reg do_wr; + + wire acc_ok,acc_err,io_acc; + wire acc_pass; + wire ca_hit; + wire [31:0] reg_adder; + wire [31:0] next_vadr; + wire [31:0] final_addr; + wire [31:0] pg_addr; + wire [1:0] inc_pack; + wire [3:0] index_sel; + wire ld_ea_i; + wire ea_ok; + wire qw_align; + wire init_acc; + wire in_page; + wire all_ok; + wire fa_out; + wire pg_test; + + // ++++++++++++++++++++ Decoding ACC_STAT from data cache ++++++++++++++++++++++++++++ + + // ACC_STAT[5:0] : CA_HIT, IO_ACC, PROT_ERROR , ABO_LEVEL1 , ABORT , ACC_OK + + assign ca_hit = ACC_STAT[5]; + assign io_acc = ACC_STAT[4]; + assign acc_err = ACC_STAT[3] | ACC_STAT[1]; // Abort or Protection Error + assign acc_ok = ACC_STAT[0] & ~pg_op; + assign acc_pass = ACC_STAT[0] & ZTEST; + + always @(posedge BCLK) ABORT <= acc_err; // Signal to Steuerung - only a pulse + + always @(posedge BCLK) if (acc_err) tex_feld <= ACC_STAT[3] ? 2'b11 : {~ACC_STAT[2],ACC_STAT[2]}; // for MSR + always @(posedge BCLK) if (acc_err) u_ddt <= {RMW,ABO_STAT[1],(WRITE_OUT | ZTEST)}; + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + always @(SRC2SEL or CLRMSW or SRC2 or PC_ARCHI or ea_reg) + case (SRC2SEL) + 2'b00 : source2 = {(CLRMSW ? 16'h0000 : SRC2[31:16]),SRC2[15:0]}; // base reg, External Addressing with MOD + 2'b01 : source2 = PC_ARCHI; // PC relative + 2'b10 : source2 = 32'h0; // Absolute Addressing + 2'b11 : source2 = ea_reg; // REUSE : 2. TOS + endcase + + assign index_sel = POST ? 4'h0 : INDEX; // Alternative application of Index for POST Adder : POP from Stack + + always @(BWD or SRC1) + casex (BWD) + 2'b00 : sign_ext_src1 = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte + 2'b01 : sign_ext_src1 = {{16{SRC1[15]}},SRC1[15:0]}; // Word + default : sign_ext_src1 = SRC1; + endcase + + always @(index_sel or sign_ext_src1 or SRC1) + casex (index_sel) + 4'b1_0xx : index_val = sign_ext_src1; // für CASE + 4'b1_1xx : index_val = {{ 3{sign_ext_src1[31]}},sign_ext_src1[31:3]}; // for Bit Opcodes + 4'b0_100 : index_val = SRC1; + 4'b0_101 : index_val = {SRC1[30:0],1'b0}; + 4'b0_110 : index_val = {SRC1[29:0],2'b00}; + 4'b0_111 : index_val = {SRC1[28:0],3'b000}; + default : index_val = 32'h0; + endcase + + assign reg_adder = source2 + index_val; // SRC2 allows simple MOV with SRC1 + + assign final_addr = reg_adder + DISP; // That's the final access address + + always @(posedge BCLK) if (LDEA && (index_sel[3:2] == 2'b11)) BITSEL <= SRC1[2:0]; // for Bit Opcodes in I_PFAD + + always @(INDEX) // SP POP Operation & String Backward + case (INDEX[2:0]) + 3'b000 : tos_offset = 32'h0000_0001; + 3'b001 : tos_offset = 32'h0000_0002; + 3'b010 : tos_offset = 32'h0000_0004; + 3'b011 : tos_offset = 32'h0000_0008; + 3'b100 : tos_offset = 32'hFFFF_FFFF; + 3'b101 : tos_offset = 32'hFFFF_FFFE; + 3'b110 : tos_offset = 32'hFFFF_FFFC; + 3'b111 : tos_offset = 32'hFFFF_FFF8; + endcase + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) ld_ea_reg <= 1'b0; + else ld_ea_reg <= (LDEA | ld_ea_reg) & ~DISP_OK; + + assign ld_ea_i = (LDEA | ld_ea_reg) & DISP_OK; + + assign ea_ok = (READ | WRITE | LDEA | ld_ea_reg) & ~FULLACC & DISP_OK; + + always @(posedge BCLK) icache_adr <= PC_ICACHE; + + // Memory for the calculated address for reuse and Register for POST modified addresses : + always @(posedge BCLK) + if (ld_ea_i) + begin + casex ({MMU_UPDATE[1],INDEX[0],POST}) + 3'b10x : ea_reg <= MMU_UPDATE[0] ? vadr_reg : icache_adr; // TEAR + 3'b11x : ea_reg <= MMU_UPDATE[0] ? + {24'h0000_00,3'b101, u_ddt, tex_feld} // MSR + : {24'h0000_00,3'b100,IC_TEX[2],ABO_STAT[0],1'b0,IC_TEX[1:0]}; // only READ from ICACHE + 3'b0x1 : ea_reg <= source2 + tos_offset ; + 3'b0x0 : ea_reg <= final_addr; + endcase + end + + assign ADDR = ea_reg; // used for ADDR opcode and TOS Addressing + + // This pulse stores all parameters of access + assign init_acc = ((FULLACC ? (NEWACC & acc_ende) : acc_ende) | ~acc_run) & DISP_OK & (READ | WRITE) & ~ABORT & NO_TRAP; + + assign fa_out = init_acc | ADIVAR; // special case for LMR IVAR,... + + always @(fa_out or acc_ok or final_addr or qw_align or pg_op or pg_areg or vadr_reg or next_vadr) + casex ({fa_out,acc_ok}) + 2'b1x : VADR = {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]}; + 2'b00 : VADR = pg_op ? {pg_areg,12'h0} : vadr_reg; + 2'b01 : VADR = next_vadr; + endcase + + always @(posedge BCLK) + if (init_acc) vadr_reg <= {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]}; + else + if (pg_op && ZTEST && acc_err) vadr_reg <= {pg_areg,12'h0}; // for TEAR ! + else + if (acc_ok) vadr_reg <= next_vadr; + + assign next_vadr = qwa_flag ? {vadr_reg[31:3],3'b000} : ({vadr_reg[31:2],2'b00} + 32'h0000_0004); + + // Logic for Page border WRITE Test + assign pg_addr = final_addr + {29'h0,(ASIZE[1] & ASIZE[0]),ASIZE[1],(ASIZE[1] | ASIZE[0])}; + always @(posedge BCLK) if (init_acc) pg_areg <= pg_addr[31:12]; + assign pg_test = (final_addr[12] != pg_addr[12]) & ~OP_RMW; // At RMW no Test necessary + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) pg_op <= 1'b0; + else + pg_op <= init_acc ? (WRITE & ~RWVAL_1 & pg_test) : (pg_op & ~acc_pass & ~acc_err); + + always @(posedge BCLK) do_wr <= pg_op & ZTEST & acc_pass; // All ok, Page exists => continue + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) READ_OUT <= 1'b0; + else + READ_OUT <= init_acc ? (READ & ~RWVAL_1) : (READ_OUT & ~acc_ende & ~acc_err); + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) write_reg <= 1'b0; + else + write_reg <= (init_acc ? (WRITE & ~RWVAL_1 & ~pg_test) : (write_reg & ~acc_ende & ~acc_err & ~FPU_TRAP)) | do_wr; + + assign WRITE_OUT = write_reg & ~FPU_TRAP; + + // Special case for RDVAL and WRVAL + always @(posedge BCLK or negedge BRESET) + if (!BRESET) ZTEST <= 1'b0; + else + ZTEST <= pg_op ? (~ZTEST | (~acc_pass & ~acc_err)) : (init_acc ? RWVAL_1 : (ZTEST & ~acc_ende & ~acc_err)); + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) RMW <= 1'b0; + else + RMW <= init_acc ? (OP_RMW & PHASE_17) : (RMW & ~acc_ende & ~acc_err); + + // Special case : first MSD access by aligned QWORD READ + assign qw_align = (final_addr[2:0] == 3'b000) & READ & (ASIZE == 2'b11); + + always @(posedge BCLK) if (init_acc) qwa_flag <= qw_align; + + always @(posedge BCLK or negedge BRESET) // central flag that shows the ADDR_UNIT is busy + if (!BRESET) acc_run <= 1'b0; + else + acc_run <= init_acc | (acc_run & ~acc_ende & ~acc_err & ~FPU_TRAP); + + always @(posedge BCLK) if (init_acc) SIZE <= ASIZE; + + assign inc_pack = (PACKET[1:0] == 2'b00) ? 2'b10 : {(SIZE[1] ^ SIZE[0]),(SIZE[1] & SIZE[0])}; + + // Counter for data packets 1 to 3 : special case aligned QWORD : only 2 packets. Additionally start address in bits 1 und 0. + // special coding (00) -> [01] -> (10) , [01] optional by QWORD and (10) shows always the end + always @(posedge BCLK) + if (init_acc) PACKET <= {2'b00,final_addr[1:0]}; + else + if (acc_ok) PACKET <= PACKET + {inc_pack,2'b00}; + + // This signal is the End signal for the ADDR_UNIT internally. + always @(SIZE or PACKET or acc_ok) + casex ({SIZE,PACKET[3],PACKET[1:0]}) + 5'b00_x_xx : acc_ende = acc_ok; // Byte + 5'b01_0_0x : acc_ende = acc_ok; // Word 1 packet + 5'b01_0_10 : acc_ende = acc_ok; // 1 packet + 5'b01_1_xx : acc_ende = acc_ok; // 2 packets + 5'b10_0_00 : acc_ende = acc_ok; // DWord 1 packet + 5'b10_1_xx : acc_ende = acc_ok; // 2 packets + 5'b11_1_xx : acc_ende = acc_ok; // QWord at least 2 packets + default : acc_ende = 1'b0; + endcase + + assign in_page = (vadr_reg[11:3] != 9'h1FF); // Access inside a page ? During WRITE address is increasing : 1. LSD 2. MSD + + always @(SIZE or vadr_reg or in_page or PACKET) + casex (SIZE) + 2'b01 : frueh_ok = (vadr_reg[3:2] != 2'b11); //Word + 2'b10 : frueh_ok = (vadr_reg[3:2] != 2'b11); //DWord + 2'b11 : frueh_ok = (PACKET[1:0] == 2'b00) ? (~vadr_reg[3] | ~vadr_reg[2]) : ((PACKET[3:2] == 2'b01) & (vadr_reg[3:2] != 2'b11)); + default : frueh_ok = 1'b1; // Byte don't case + endcase + + assign all_ok = SIZE[1] ? (PACKET[1:0] == 2'b00) : (PACKET[1:0] != 2'b11); // for DWord : Word + + always @(SIZE or READ_OUT or frueh_ok or PACKET or all_ok or io_acc or acc_ok or qwa_flag or io_rdy or ca_hit) + casex ({SIZE,READ_OUT,frueh_ok,PACKET[3],io_acc,all_ok}) + 7'b00_xxxx_x : acc_step = acc_ok; // Byte, all ok + // + 7'b01_xxxx_1 : acc_step = acc_ok; // Word : aligned access , only 1 packet + 7'b01_1x1x_0 : acc_step = acc_ok; // READ must wait for all data + 7'b01_0x1x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet + 7'b01_0100_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet + // + 7'b10_xxxx_1 : acc_step = acc_ok; // DWord : aligned access , only 1 packet + 7'b10_1x1x_0 : acc_step = acc_ok; // READ must wait for all data + 7'b10_0x1x_0 : acc_step = acc_ok; // WRITE Adr. ist not perfect and waits for last packet + 7'b10_0100_0 : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet + // fast QWord READ : there would be a 2. acc_step if not ~PACK... + 7'b11_1xxx_x : acc_step = acc_ok & ( (qwa_flag & ~io_rdy & ca_hit) ? ~PACKET[3] : PACKET[3] ); + 7'b11_0x1x_x : acc_step = acc_ok; + 7'b11_0100_x : acc_step = acc_ok; // WRITE Adr. perfect - acc_step after 1. packet if not io_acc + default : acc_step = 1'b0; + endcase + + // There is a 2. acc_step if packet (10) - this must be suppressed + always @(posedge BCLK or negedge BRESET) + if (!BRESET) no_done <= 1'b0; + else no_done <= (~acc_ende & acc_step) | (no_done & ~(acc_run & acc_ende)); + + // The final DONE Multiplexer + assign ACC_DONE = acc_run ? (acc_step & ~no_done) : ea_ok; + + // Bugfix of 7.October 2015 + always @(posedge BCLK) QWATWO <= acc_run & acc_ok & qwa_flag & ~io_rdy & ca_hit & ~PACKET[3] & (SIZE == 2'b11) & READ_OUT & ~no_done; + + always @(posedge BCLK) reg_out_i <= ~acc_step & BRESET & ((qwa_flag & (io_rdy | ~ca_hit) & acc_ok) | reg_out_i); + + always @(posedge BCLK) io_rdy <= IO_READY & (WRITE_OUT | READ_OUT); + + always @(posedge BCLK) next_reg <= (acc_step & ~qwa_flag) & (SIZE == 2'b11); + assign REG_OUT = reg_out_i | next_reg; + +endmodule diff --git a/src/m32632/ALIGNER.v b/src/m32632/ALIGNER.v new file mode 100644 index 0000000..5cde89e --- /dev/null +++ b/src/m32632/ALIGNER.v @@ -0,0 +1,354 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: ALIGNER.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. WR_ALINGER alignes write data to cache and external devices +// 2. RD_ALINGER alignes read data for the data path +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. WR_ALINGER alignes write data to cache and external devices +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module WR_ALIGNER ( PACKET, DP_Q, SIZE, WRDATA, ENBYTE ); + + input [3:0] PACKET; // [3:2] Paketnumber , [1:0] Startaddress + input [63:0] DP_Q; + input [1:0] SIZE; + output [31:0] WRDATA; + output [3:0] ENBYTE; + + reg [3:0] ENBYTE; + reg [7:0] dbyte0,dbyte1,dbyte2,dbyte3; + wire switch; + +// Data packet [ B7 ],[ B6 ],[ B5 ],[ B4 ],[ B3 ],[ B2 ],[ B1 ],[ B0 ] +// Address , i.e. 001 : one DWORD +// gives 2 packets : 1. packet [-B6-----B5-----B4-] +// 2. packet, Address + 4 [-B7-] +// Addresse , i.e. 010 : one QWORD +// gives 3 packets : 1. packet [-B1-----B0-] +// 2. packet, Address + 4 [-B5-----B4-----B3-----B2-] +// 3. packet, Address + 8 [-B7-----B6-] + +// SIZE PACKET ADR : Outputbus +// 00 00 00 x x x B4 +// 00 00 01 x x B4 x +// 00 00 10 x B4 x x +// 00 00 11 B4 x x x + +// 01 00 00 x x B5 B4 +// 01 00 01 x B5 B4 x +// 01 00 10 B5 B4 x x +// 01 00 11 B4 x x x +// 01 10 11 x x x B5 + +// 10 00 00 B7 B6 B5 B4 +// 10 00 01 B6 B5 B4 x +// 10 10 01 x x x B7 +// 10 00 10 B5 B4 x x +// 10 10 10 x x B7 B6 +// 10 00 11 B4 x x x +// 10 10 11 x B7 B6 B5 + +// 11 00 00 B3 B2 B1 B0 +// 11 10 00 B7 B6 B5 B4 +// 11 00 01 B2 B1 B0 x +// 11 01 01 B6 B5 B4 B3 +// 11 10 01 x x x B7 +// 11 00 10 B1 B0 x x +// 11 01 10 B5 B4 B3 B2 +// 11 10 10 x x B7 B6 +// 11 00 11 B0 x x x +// 11 01 11 B4 B3 B2 B1 +// 11 10 11 x B7 B6 B5 + + assign switch = (SIZE == 2'b11) & (PACKET[3:2] == 2'b00); + + always @(DP_Q or switch or PACKET) + case (PACKET[1:0]) + 2'b00 : dbyte0 = switch ? DP_Q[7:0] : DP_Q[39:32]; + 2'b01 : dbyte0 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24]; + 2'b10 : dbyte0 = PACKET[3] ? DP_Q[55:48] : DP_Q[23:16]; + 2'b11 : dbyte0 = PACKET[3] ? DP_Q[47:40] : DP_Q[15:8]; + endcase + + always @(DP_Q or switch or PACKET) + case (PACKET[1:0]) + 2'b00 : dbyte1 = switch ? DP_Q[15:8] : DP_Q[47:40]; + 2'b01 : dbyte1 = switch ? DP_Q[7:0] : DP_Q[39:32]; + 2'b10 : dbyte1 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24]; + 2'b11 : dbyte1 = PACKET[3] ? DP_Q[55:48] : DP_Q[23:16]; + endcase + + always @(DP_Q or switch or PACKET) + case (PACKET[1:0]) + 2'b00 : dbyte2 = switch ? DP_Q[23:16] : DP_Q[55:48]; + 2'b01 : dbyte2 = switch ? DP_Q[15:8] : DP_Q[47:40]; + 2'b10 : dbyte2 = switch ? DP_Q[7:0] : DP_Q[39:32]; + 2'b11 : dbyte2 = PACKET[3] ? DP_Q[63:56] : DP_Q[31:24]; + endcase + + always @(DP_Q or switch or PACKET) + case (PACKET[1:0]) + 2'b00 : dbyte3 = switch ? DP_Q[31:24] : DP_Q[63:56]; + 2'b01 : dbyte3 = switch ? DP_Q[23:16] : DP_Q[55:48]; + 2'b10 : dbyte3 = switch ? DP_Q[15:8] : DP_Q[47:40]; + 2'b11 : dbyte3 = switch ? DP_Q[7:0] : DP_Q[39:32]; + endcase + + assign WRDATA = {dbyte3,dbyte2,dbyte1,dbyte0}; + + always @(SIZE or PACKET) + casex ({SIZE,PACKET}) + 6'b00_xx_00 : ENBYTE = 4'b0001; // BYTE + 6'b00_xx_01 : ENBYTE = 4'b0010; + 6'b00_xx_10 : ENBYTE = 4'b0100; + 6'b00_xx_11 : ENBYTE = 4'b1000; + // + 6'b01_xx_00 : ENBYTE = 4'b0011; // WORD + 6'b01_xx_01 : ENBYTE = 4'b0110; + 6'b01_xx_10 : ENBYTE = 4'b1100; + 6'b01_0x_11 : ENBYTE = 4'b1000; + 6'b01_1x_11 : ENBYTE = 4'b0001; + // + 6'b11_xx_00 : ENBYTE = 4'b1111; // QWORD + 6'b11_00_01 : ENBYTE = 4'b1110; + 6'b11_01_01 : ENBYTE = 4'b1111; + 6'b11_1x_01 : ENBYTE = 4'b0001; + 6'b11_00_10 : ENBYTE = 4'b1100; + 6'b11_01_10 : ENBYTE = 4'b1111; + 6'b11_1x_10 : ENBYTE = 4'b0011; + 6'b11_00_11 : ENBYTE = 4'b1000; + 6'b11_01_11 : ENBYTE = 4'b1111; + 6'b11_1x_11 : ENBYTE = 4'b0111; + // + 6'b10_xx_00 : ENBYTE = 4'b1111; // DWORD + 6'b10_0x_01 : ENBYTE = 4'b1110; + 6'b10_1x_01 : ENBYTE = 4'b0001; + 6'b10_0x_10 : ENBYTE = 4'b1100; + 6'b10_1x_10 : ENBYTE = 4'b0011; + 6'b10_0x_11 : ENBYTE = 4'b1000; + 6'b10_1x_11 : ENBYTE = 4'b0111; + endcase + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. RD_ALINGER alignes read data for the data path +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module RD_ALIGNER ( BCLK, ACC_OK, PACKET, SIZE, REG_OUT, RDDATA, CA_HIT, DP_DI, AUX_QW ); + + input BCLK; + input ACC_OK; + input [3:0] PACKET; // [3:2] Paketnumber , [1:0] Startaddress + input [1:0] SIZE; + input REG_OUT; + input [31:0] RDDATA; + input CA_HIT; + + output [31:0] DP_DI; + output reg AUX_QW; + + reg [6:0] enable; + reg [7:0] dreg_0,dreg_1,dreg_2,dreg_3,dreg_4,dreg_5,dreg_6; + reg [7:0] out_0,out_1,out_2,out_3; + +// RD_ALIGNER principal working : 10 is last packet , 01 is packet in between + +// Not aligned QWORD : ADR[1:0] = 3 i.e. +// Bytes to datapath : . - . - 4 - 4 +// Bytes from memory : 1 - 4 - 3 - . +// ACC_DONE : _______/----\__ +// + 1 cycle ____/-- +// at the end 2 cycles lost. ACC_DONE informs the Op-Dec that data is available and sent one clock cycle later +// the LSD of QWORD access. (ACC_DONE -> REG_OUT is happening in ADDR_UNIT.) +// +// SIZE PACKET ADR : Output data ACC_OK +// 00 -- 00 x x x B0 Byte 1 +// 00 -- 01 x x x B1 1 +// 00 -- 10 x x x B2 1 +// 00 -- 11 x x x B3 1 + +// 01 00 00 x x B1 B0 Word 1 +// 01 00 01 x x B2 B1 1 +// 01 00 10 x x B3 B2 1 +// 01 00 11 B3 x x x -> Reg : R4 - - - 0 +// 01 10 11 x x B0 R4 1 + +// 10 00 00 B3 B2 B1 B0 DWORD 1 +// 10 00 01 B3 B2 B1 x -> Reg : R6 R5 R4 - 0 +// 10 10 01 B0 R6 R5 R4 1 +// 10 00 10 B3 B2 x x -> Reg : R5 R4 - - 0 +// 10 10 10 B1 B0 R5 R4 1 +// 10 00 11 B3 x x x -> Reg : R4 - - - 0 +// 10 10 11 B2 B1 B0 R4 1 + +// 11 00 00 B3 B2 B1 B0 QWORD 1 MSD +// 11 01 00 B3 B2 B1 B0 not out of Reg! 0 LSD +// 11 00 01 B3 B2 B1 x -> Reg : R2 R1 R0 - 0 +// 11 01 01 B3 B2 B1 B0 -> Reg : R6 R5 R4 R3 0 +// 11 10 01 B0 R6 R5 R4 1 MSD +// next cycle: R3 R2 R1 R0 LSD +// 11 00 10 B3 B2 x x -> Reg : R1 R0 - - 0 +// 11 01 10 B3 B2 B1 B0 -> Reg : R5 R4 R3 R2 0 +// 11 10 10 B1 B0 R5 R4 1 MSD +// next cycle: R3 R2 R1 R0 LSD +// 11 00 11 B3 x x x -> Reg : R0 - - - 0 +// 11 01 11 B3 B2 B1 B0 -> Reg : R4 R3 R2 R1 0 +// 11 10 11 B2 B1 B0 R4 1 MSD +// next cycle: R3 R2 R1 R0 LSD + +// IO_ACCESS QWORD : +// 11 00 00 B3 B2 B1 B0 -> Reg : R3 R2 R1 R0 0 +// 11 01 00 R3 R2 R1 R0 -> Reg : R3 R2 R1 R0 1 MSD +// next cycle: R3 R2 R1 R0 LSD + + always @(ACC_OK or SIZE or PACKET) + casex ({ACC_OK,SIZE,PACKET}) + 7'b1_xx_0x_00 : enable = 7'b000_1111; + 7'b1_01_0x_11 : enable = 7'b001_0000; + 7'b1_10_0x_01 : enable = 7'b111_0000; + 7'b1_10_0x_10 : enable = 7'b011_0000; + 7'b1_10_0x_11 : enable = 7'b001_0000; + 7'b1_11_00_01 : enable = 7'b000_0111; // QWORD + 7'b1_11_01_01 : enable = 7'b111_1000; + 7'b1_11_00_10 : enable = 7'b000_0011; + 7'b1_11_01_10 : enable = 7'b011_1100; + 7'b1_11_00_11 : enable = 7'b000_0001; + 7'b1_11_01_11 : enable = 7'b001_1110; + default : enable = 7'b000_0000; + endcase + +// Register for inbetween data: simple multiplexer + + always @(posedge BCLK) + if (enable[0]) + case (PACKET[1:0]) + 2'b01 : dreg_0 <= RDDATA[15:8]; + 2'b10 : dreg_0 <= RDDATA[23:16]; + 2'b11 : dreg_0 <= RDDATA[31:24]; + default : dreg_0 <= RDDATA[7:0]; + endcase + + always @(posedge BCLK) + if (enable[1]) + case (PACKET[1:0]) + 2'b01 : dreg_1 <= RDDATA[23:16]; + 2'b10 : dreg_1 <= RDDATA[31:24]; + 2'b11 : dreg_1 <= RDDATA[7:0]; + default : dreg_1 <= RDDATA[15:8]; + endcase + + always @(posedge BCLK) + if (enable[2]) + case (PACKET[1:0]) + 2'b01 : dreg_2 <= RDDATA[31:24]; + 2'b10 : dreg_2 <= RDDATA[7:0]; + 2'b11 : dreg_2 <= RDDATA[15:8]; + default : dreg_2 <= RDDATA[23:16]; + endcase + + always @(posedge BCLK) + if (enable[3]) + case (PACKET[1:0]) + 2'b01 : dreg_3 <= RDDATA[7:0]; + 2'b10 : dreg_3 <= RDDATA[15:8]; + 2'b11 : dreg_3 <= RDDATA[23:16]; + default : dreg_3 <= RDDATA[31:24]; + endcase + + always @(posedge BCLK) + if (enable[4]) + case (PACKET[1:0]) + 2'b01 : dreg_4 <= RDDATA[15:8]; + 2'b10 : dreg_4 <= RDDATA[23:16]; + 2'b11 : dreg_4 <= RDDATA[31:24]; + default : dreg_4 <= dreg_4; + endcase + + always @(posedge BCLK) if (enable[5]) dreg_5 <= PACKET[1] ? RDDATA[31:24] : RDDATA[23:16]; + + always @(posedge BCLK) if (enable[6]) dreg_6 <= RDDATA[31:24]; + + // +++++++++++++++++++++++ + + always @(SIZE or PACKET or RDDATA or dreg_0 or dreg_4) + casex ({SIZE,PACKET[3],PACKET[1:0]}) + 5'b0x_0_01 : out_0 = RDDATA[15:8]; + 5'b0x_0_10 : out_0 = RDDATA[23:16]; + 5'b00_0_11 : out_0 = RDDATA[31:24]; + 5'b01_1_11 : out_0 = dreg_4; + 5'b1x_1_01 : out_0 = dreg_4; + 5'b1x_1_1x : out_0 = dreg_4; + default : out_0 = RDDATA[7:0]; + endcase + + always @(SIZE or PACKET or RDDATA or dreg_1 or dreg_5) + casex ({SIZE,PACKET[3],PACKET[1:0]}) + 5'b01_0_01 : out_1 = RDDATA[23:16]; + 5'b01_0_10 : out_1 = RDDATA[31:24]; + 5'bxx_x_11 : out_1 = RDDATA[7:0]; + 5'b1x_1_01 : out_1 = dreg_5; + 5'b1x_1_10 : out_1 = dreg_5; + default : out_1 = RDDATA[15:8]; + endcase + + always @(SIZE or PACKET or RDDATA or dreg_2 or dreg_6) + case ({SIZE[1],PACKET[3],PACKET[1:0]}) + 4'b1_1_01 : out_2 = dreg_6; + 4'b1_1_10 : out_2 = RDDATA[7:0]; + 4'b1_1_11 : out_2 = RDDATA[15:8]; + default : out_2 = RDDATA[23:16]; + endcase + + always @(SIZE or PACKET or RDDATA or dreg_3) + case ({SIZE[1],PACKET[3],PACKET[1:0]}) + 4'b1_1_01 : out_3 = RDDATA[7:0]; + 4'b1_1_10 : out_3 = RDDATA[15:8]; + 4'b1_1_11 : out_3 = RDDATA[23:16]; + default : out_3 = RDDATA[31:24]; + endcase + + assign DP_DI = REG_OUT ? {dreg_3,dreg_2,dreg_1,dreg_0} : {out_3,out_2,out_1,out_0}; + + // ++++++++++++++++ Special case QWord if cache switched off +++++++++++++++++++ + + always @(posedge BCLK) AUX_QW <= ACC_OK & ~CA_HIT & (SIZE == 2'b11) & PACKET[3]; + +endmodule diff --git a/src/m32632/CACHE_LOGIK.v b/src/m32632/CACHE_LOGIK.v new file mode 100644 index 0000000..74c8f2d --- /dev/null +++ b/src/m32632/CACHE_LOGIK.v @@ -0,0 +1,784 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: CACHE_LOGIK.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 7 October 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. DEBUG_AE Debug unit for address compare in data cache +// 2. MMU_UP MMU memory update and initalization controller +// 3. DCA_CONTROL Data cache valid memory update and initalization controller +// 4. MMU_MATCH MMU virtual address match detector +// 5. CA_MATCH Cache tag match detector +// 6. DCACHE_SM Data cache state machine +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. DEBUG_AE Debug unit for address compare in data cache +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT ); + + input [40:2] DBG_IN; + + input READ,WRITE; + input USER; + input VIRTUELL; + input ACC_OK; + input [31:2] VADR_R; + input [19:0] MMU_Q; + input [3:0] ENBYTE; + + output DBG_HIT; + + wire sd,ud,crd,cwr,vnp; + wire make; + wire virt_adr,real_adr,page_adr; + wire byte_en; + + assign sd = DBG_IN[40]; + assign ud = DBG_IN[39]; + assign crd = DBG_IN[38]; + assign cwr = DBG_IN[37]; + assign vnp = DBG_IN[36]; + + assign make = ((ud & USER) | (sd & ~USER)) // compare USER or SUPERVISOR + & (VIRTUELL == vnp) // compare real or virtual address + & ((cwr & WRITE) | (crd & READ)); // compare READ or WRITE + + assign virt_adr = (MMU_Q == DBG_IN[31:12]); + assign real_adr = (VADR_R[31:12] == DBG_IN[31:12]); + assign page_adr = (VADR_R[11:2] == DBG_IN[11:2]); + + assign byte_en = |(ENBYTE & DBG_IN[35:32]); + + assign DBG_HIT = ACC_OK // all valid + & make // selection is valid + & (VIRTUELL ? virt_adr : real_adr) & page_adr // address + & byte_en; // Byte Enable + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. MMU_UP MMU memory update and initalization controller +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE, + WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN ); + + input BCLK; + input BRESET; + input NEW_PTB; // the MMU memory is cleared. Pulse of one BCLK cycle, Op-Dec is waiting + input PTB1; // which one + input IVAR; + input WR_MRAM; // BCLK : update MRAM and MMU_VAL + input [19:16] VADR,VADR_R; // For update + input [31:0] MVALID,UPDATE; + + output WE_MV; // Write Enable MMU Valid + output [3:0] WADR_MV,RADR_MV; + output [31:0] DAT_MV; + output NEW_PTB_RUN; + + reg neue_ptb,wr_flag,old_rst,run_over; + reg [3:0] count; + + wire [15:0] new_val; + + assign WE_MV = wr_flag | WR_MRAM | IVAR; // write on falling edge BCLK + assign RADR_MV = run_over ? count : VADR; + assign WADR_MV = wr_flag ? (count - 4'b0001) : VADR_R; + assign DAT_MV = wr_flag ? {MVALID[31:16],new_val} : UPDATE; // Only the matching entries are cleared : PTB0/PTB1 + + // [31:16] Address-Space memory, [15:0] Valid memory + assign new_val = neue_ptb ? (PTB1 ? (MVALID[15:0] & ~MVALID[31:16]) : (MVALID[15:0] & MVALID[31:16])) : 16'h0; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) neue_ptb <= 1'b0; + else neue_ptb <= NEW_PTB | (neue_ptb & run_over); + + always @(posedge BCLK) old_rst <= BRESET; // after Reset all will be set to 0 + + always @(posedge BCLK) run_over <= ((~old_rst | NEW_PTB) | (run_over & (count != 4'hF))) & BRESET; + + always @(posedge BCLK) count <= run_over ? count + 4'h1 : 4'h0; + + always @(posedge BCLK) wr_flag <= run_over; + + assign NEW_PTB_RUN = wr_flag; // Info to Op-Dec + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. DCA_CONTROL Data cache valid memory update and initalization controller +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DCA_CONTROL ( BCLK, MCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, WRCFG, VADR_R, UPDATE, INVAL_A, WRITE, + WCTRL, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 ); + + input BCLK; + input MCLK; + input BRESET; + input CUPDATE; // State CUPDATE : Cache is filled from DRAM + input DRAM_ACC; + input CA_SET; + input HIT_ALL; // a complete cache hit ! + input WRCFG; // static signal : GND or VDD + input [11:7] VADR_R; + input [23:0] UPDATE; + input INVAL_A; + input WRITE; + input [1:0] WCTRL; // [1] : Read Burst Signal from DRAM controller, MCLK aligned. [0] : Cache inhibit + input KILL; // valid Ram must be updated because of collision ... or CINV + + output WRCRAM0,WRCRAM1; + output WE_CV; + output [4:0] WADR_CV; + output [23:0] DAT_CV; + output INIT_CA_RUN; + output WRSET0,WRSET1; + + reg [1:0] state; + reg [4:0] acount; + reg ca_set_d; + + reg dly_bclk,zero,wr_puls; + reg [2:0] count,refer; + + wire countf; + + // physical address is stored in TAG-RAM + + assign WRCRAM0 = (CUPDATE & ~WCTRL[0]) & ~CA_SET; + assign WRCRAM1 = (CUPDATE & ~WCTRL[0]) & CA_SET; + + // Load Valid RAM : + + assign WE_CV = state[1] | HIT_ALL | (CUPDATE & ~WCTRL[0]) | KILL; // Hit All for "Last" Update + assign WADR_CV = state[1] ? acount : VADR_R; + assign DAT_CV = state[1] ? 24'h0 : UPDATE; + + // Clear of Cache-Valid RAMs : 32 clocks of BCLK + + assign countf = (acount == 5'h1F); + + always @(posedge BCLK) + casex ({BRESET,INVAL_A,countf,state[1:0]}) + 5'b0xx_xx : state <= 2'b01; + 5'b1xx_01 : state <= 2'b10; // start counter + 5'b10x_00 : state <= 2'b00; // wait ... + 5'b11x_00 : state <= 2'b10; + 5'b1x0_10 : state <= 2'b10; + 5'b1x1_10 : state <= 2'b00; + default : state <= 2'b0; + endcase + + always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01; + + assign INIT_CA_RUN = state[1]; + + always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET; + + // WRITE Control in data RAMs + assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ~ca_set_d); + assign WRSET1 = ( CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ca_set_d); + + // ++++++++++++ Special circuit for Timing of write pulse for data RAM of data cache +++++++++ + + always @(negedge MCLK) dly_bclk <= BCLK; + + always @(negedge MCLK) zero <= BCLK & ~dly_bclk; + + always @(posedge MCLK) if (zero) count <= 3'd0; else count <= count + 3'd1; + + // count at zero , ref Wert + // 1 : --- always on 5 : 100 001 + // 2 : 001 000 6 : 101 010 + // 3 : 010 010 7 : 110 011 + // 4 : 011 000 8 : 111 100 + always @(posedge MCLK) if (zero) refer <= {(count == 3'd7),((count == 3'd5) | (count[1:0] == 2'b10)),(count[2] & ~count[0])}; + + always @(posedge MCLK) wr_puls <= (count == refer) | WRCFG; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. MMU_MATCH MMU virtual address match detector +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR, + VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 ); + + input USER; + input READ; + input WRITE; + input RMW; + input [2:0] MCR_FLAGS; + input [31:0] MVALID; + input [31:12] VADR_R; + input [31:16] MMU_VA; + input [1:0] IVAR; // Invalidate Entry + + output VIRTUELL; // only for Adress-Mux + output MMU_HIT; + output [31:0] UPDATE; + output reg PROT_ERROR; // if valid must suppress write in Write Buffer and cache + output CI,SEL_PTB1; + + reg [15:0] maske; + + wire adr_space,as_sorte,match,alles_ok; + wire [15:0] val_bits,as_bits; + wire ena_prot; + wire zugriff; + + assign zugriff = READ | WRITE; + + always @(VADR_R) + case (VADR_R[15:12]) + 4'h0 : maske = 16'h0001; + 4'h1 : maske = 16'h0002; + 4'h2 : maske = 16'h0004; + 4'h3 : maske = 16'h0008; + 4'h4 : maske = 16'h0010; + 4'h5 : maske = 16'h0020; + 4'h6 : maske = 16'h0040; + 4'h7 : maske = 16'h0080; + 4'h8 : maske = 16'h0100; + 4'h9 : maske = 16'h0200; + 4'hA : maske = 16'h0400; + 4'hB : maske = 16'h0800; + 4'hC : maske = 16'h1000; + 4'hD : maske = 16'h2000; + 4'hE : maske = 16'h4000; + 4'hF : maske = 16'h8000; + endcase + + assign VIRTUELL = USER ? MCR_FLAGS[0] : MCR_FLAGS[1]; + + assign adr_space = IVAR[1] ? IVAR[0] : (MCR_FLAGS[2] & USER); // adr_space = IVARx ? 1 or 0 : DualSpace & TU + + assign as_sorte = ((MVALID[31:16] & maske) != 16'h0); + + assign match = (VADR_R[31:20] == MMU_VA[31:20]) & (adr_space == as_sorte) & ((MVALID[15:0] & maske) != 16'h0000); + + assign alles_ok = match & ( ~WRITE | MMU_VA[17] ) & ~PROT_ERROR; // Modified - Flag : reload the PTE + + // if MMU_HIT = 0 then there is no Write-Buffer access abd no update of cache ! + assign MMU_HIT = zugriff ? ( VIRTUELL ? alles_ok : 1'b1 ) : 1'b0 ; // MMU off : then always HIT + + assign val_bits = IVAR[1] ? (MVALID[15:0] & (match ? ~maske : 16'hFFFF)) : (MVALID[15:0] | maske); + assign as_bits = IVAR[1] ? MVALID[31:16] : (adr_space ? (MVALID[31:16] | maske) : (MVALID[31:16] & ~maske)); + + assign UPDATE = {as_bits,val_bits}; + + assign ena_prot = zugriff & VIRTUELL & match; + + // A Protection error must suppress write in WB and cache + always @(ena_prot or MMU_VA or USER or WRITE or RMW) + case ({ena_prot,MMU_VA[19:18]}) + 3'b100 : PROT_ERROR = USER | WRITE | RMW; // Only Supervisor READ + 3'b101 : PROT_ERROR = USER; // no USER access + 3'b110 : PROT_ERROR = USER & (WRITE | RMW); // USER only READ + default : PROT_ERROR = 1'b0; + endcase + + assign CI = VIRTUELL & MMU_VA[16]; + assign SEL_PTB1 = adr_space; // For PTE update + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 5. CA_MATCH Cache tag match detector +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module CA_MATCH ( CVALID, IOSEL, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO, + CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL ); + + input [23:0] CVALID; + input [3:0] IOSEL; + input [27:4] ADDR; + input [27:12] TAG0,TAG1; + input [1:0] CFG; // LDC , DC + input WRITE; + input MMU_HIT; + input CI; + input INVAL_L; // invalid cache line + input KDET; + input ENDRAM; + input DC_ILO; // CBITI/SBITI special case + + output CA_HIT; + output CA_SET; // if no Hit then says SET where to store + output [23:0] UPDATE; // Update Information for CVALID memory + output IO_SPACE; + output USE_CA; + output WB_ACC; + output KILL; + + reg [7:0] maske; + + wire match_0,match_1; + wire valid_0,valid_1; + wire select; + wire clear; + wire [7:0] update_0,update_1,lastinfo; + wire sel_dram; + + always @(ADDR) + case (ADDR[6:4]) + 3'h0 : maske = 8'h01; + 3'h1 : maske = 8'h02; + 3'h2 : maske = 8'h04; + 3'h3 : maske = 8'h08; + 3'h4 : maske = 8'h10; + 3'h5 : maske = 8'h20; + 3'h6 : maske = 8'h40; + 3'h7 : maske = 8'h80; + endcase + + assign valid_0 = (( CVALID[7:0] & maske) != 8'h00); + assign valid_1 = ((CVALID[15:8] & maske) != 8'h00); + + assign match_0 = ( TAG0 == ADDR[27:12] ); // 4KB + assign match_1 = ( TAG1 == ADDR[27:12] ); // 4KB + + assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0]; + + // which SET is written in cache miss ? If both are valid the last used is not taken + assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0; // Last-used field = CVALID[23:16] + + assign CA_SET = CA_HIT ? (valid_1 & match_1) : select; + + assign clear = INVAL_L | KDET; // INVAL_L is from CINV + + assign update_0 = CA_SET ? CVALID[7:0] : (clear ? (CVALID[7:0] & ~maske) : (CVALID[7:0] | maske)); + assign update_1 = CA_SET ? (clear ? (CVALID[15:8] & ~maske) : (CVALID[15:8] | maske)) : CVALID[15:8]; + + assign lastinfo = CA_HIT ? (CA_SET ? (CVALID[23:16] | maske) : (CVALID[23:16] & ~maske)) : CVALID[23:16]; + + assign UPDATE = {lastinfo,update_1,update_0}; + + assign KILL = clear & CA_HIT & ~CFG[1]; // only if cache is not locked + + assign sel_dram = (IOSEL == 4'b0000) & ENDRAM; // at the moment the first 256 MB of memory + assign IO_SPACE = ~sel_dram; // not DRAM or DRAM ist off + assign USE_CA = ~CI & ~DC_ILO & CFG[0] & ~CFG[1]; // CI ? ILO ? Cache on ? Locked Cache ? + assign WB_ACC = WRITE & MMU_HIT & sel_dram; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 6. DCACHE_SM Data cache state machine +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW, CAPDAT, VADR_R, IC_VA, + USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, FILLRAM, ICTODC, + RWVAL, VIRTUELL, QWATWO, + DRAM_ACC, DRAM_WR, IO_ACC, IO_RD, IO_WR, PTE_MUX, PD_MUX, PKEEP, PTE_ADR, PTE_DAT, HIT_ALL, ACC_OK, + ABORT, PROTECT, IACC_STAT, ABO_LEVEL1, WR_MRAM, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE, MMU_DIN, IC_SIGS, KOMUX, + KDET, DMA_MUX, HLDA, RWVFLAG, PTE_STAT ); + + input BCLK; + input BRESET; + input IO_SPACE; + input MDONE; // Memory Done : feedback from DRAM Controller, BCLK aligned ! + input IO_READY; + input MMU_HIT,CA_HIT; + input READ,WRITE,ZTEST,RMW; + input [31:0] CAPDAT; + input [31:12] VADR_R,IC_VA; + input USE_CA; + input PTB_WR,PTB_SEL; + input SEL_PTB1; + input [27:12] CPU_OUT; // used for PTB0/1 + input USER; + input PROT_ERROR; + input WB_ACC; + input ENWR; // Enable WRITE from DRAM + input ADR_EQU; + input IC_PREQ; + input FILLRAM; + input [3:0] ICTODC; // multiple signals from ICACHE, especially DMA + input [1:0] RWVAL; // RDVAL+WRVAL Operation + input VIRTUELL; // for RDVAL/WRVAL + input QWATWO; + + output reg DRAM_ACC,DRAM_WR; + output IO_ACC,IO_RD,IO_WR; + output PTE_MUX,PD_MUX,PKEEP; + output [27:0] PTE_ADR; + output [19:0] PTE_DAT; + output HIT_ALL; + output ACC_OK; + output ABORT,PROTECT; + output [3:1] IACC_STAT; + output ABO_LEVEL1; + output WR_MRAM; + output CUPDATE; + output AUX_DAT; + output reg NEW_PTB; + output reg PTB_ONE; + output [23:0] MMU_DIN; + output [1:0] IC_SIGS; + output KOMUX; + output KDET; // Signal for detection of collision + output DMA_MUX; + output HLDA; // active low + output RWVFLAG; // RDVAL/WRVAL result + output [1:0] PTE_STAT; + + reg IO_WR,IO_RD; + reg [1:0] pl_dat; + reg [6:0] new_state; + reg [2:0] cap_dat; // only for analyse of timing + reg mem_done; + reg rd_done; + reg [2:0] pstate; + reg pte_run_wr; + reg [1:0] prot_level1; + reg card_flag; + reg [27:12] ptb0,ptb1; + reg write_ok; + reg icp_acc; + reg pte_modi; + reg [2:0] ko_state; + reg dma_run; + reg dma_kdet; + reg rwv_bit; + reg prot_i; + reg rd_rdy; + + wire [27:12] ptb10; + wire [31:12] virtual_adr; + wire io_busy; + wire dram_go; + wire pte_sel; + wire pte_acc; + wire do_ca_rd,pte_go,do_ic_p; + wire valid,valid_a,refer,modi; + wire level1,level2; + wire rd_level2; + wire wr_req; + wire wr_dram; + wire wr_icmram; + wire rd_ende; + wire pte_dat_8; + wire pte_wr_sig; + wire run_dc; + wire kostart; + wire dma; + wire dma_go; + wire zugriff; + wire mmu_hit_i; + wire do_zt; + wire zt_ok; + wire [1:0] acc_level; + wire user_ptw,wr_ptw; + wire pte_puls; + + always @(posedge BCLK) cap_dat <= CAPDAT[2:0]; + + // if USER not virtual then ZTEST is quickly done + assign zugriff = READ | WRITE | (ZTEST & VIRTUELL); + assign mmu_hit_i = MMU_HIT & ~ZTEST; + + // WB_ACC is a successful WRITE access, ICTODC[0] is coherent Logik release : >=3 entries in FIFO + assign wr_req = WB_ACC & ((ENWR & ICTODC[0]) | (DRAM_WR & ADR_EQU)); // release done by DRAM signal ENWR + + assign rd_ende = CA_HIT | rd_rdy; // CA_HIT only when Cache activ ! + + always @( zugriff // READ or WRITE or ZTEST , global control + or PROT_ERROR // must not be + // + or IO_SPACE // access of IO world + or io_busy // is access already running ? + // + or mmu_hit_i // Hit in MMU , now only a READ can happen + or READ + or wr_req + or rd_ende // Cache Hit + // + or DRAM_ACC // DRAM Access : shows an active state + or pte_acc // PTE access is running + // + or IC_PREQ // PTE Request from ICACHE + // + or dma // DMA Request + or dma_run ) // DMA running + // #_# #_# #_# #_# + casex ({zugriff,PROT_ERROR,IO_SPACE,io_busy,mmu_hit_i,READ,wr_req,rd_ende,DRAM_ACC,pte_acc,IC_PREQ,dma,dma_run}) + // MMU Miss : PTE load from memory , valid too if WRITE and M=0 + 13'b10_xx_0xxx_x0_x_x0 : new_state = 7'b0001010; // start PTE access + // IO-Address selected : external access starts if not busy because of WRITE + 13'b10_10_1xxx_x0_x_x0 : new_state = 7'b0000001; + // DRAM access : Cache Miss at READ : + 13'b10_0x_1100_00_x_x0 : new_state = 7'b0010010; + // DRAM access : WRITE + 13'b10_0x_101x_x0_x_x0 : new_state = 7'b0000100; + // PTE Request ICACHE , IO access with WRITE is stored - parallel DRAM access possible + 13'b0x_xx_xxxx_x0_1_00 : new_state = 7'b0101010; // no access + 13'b10_0x_1101_x0_1_x0 : new_state = 7'b0101010; // if successful READ a PTE access can happen in parallel + // DMA access. Attention : no IO-Write access in background and no ICACHE PTE access ! + 13'b0x_x0_xxxx_xx_0_10 : new_state = 7'b1000000; // DMA access is started + default : new_state = 7'b0; + endcase + + assign IO_ACC = new_state[0]; // to load registers for data, addr und BE, signal one pulse + assign dram_go = new_state[1] | rd_level2 ; + assign wr_dram = new_state[2]; // pulse only + assign pte_go = new_state[3]; + assign do_ca_rd = new_state[4]; + assign do_ic_p = new_state[5]; + assign dma_go = new_state[6]; + + // ZTEST logic is for the special case when a write access is crossing page boundaries + + assign do_zt = ZTEST & ~icp_acc; + + // 0 is pass , 1 is blocked. RWVAL[0] is 1 if WRVAL. Level 1 can only be blocked, otherwise ABORT or Level 2 is following. + always @(posedge BCLK) if (mem_done) rwv_bit <= level2 ? ~(cap_dat[2] & (~RWVAL[0] | cap_dat[1])) : 1'b1; + + assign RWVFLAG = VIRTUELL & rwv_bit; + + assign zt_ok = mem_done & (RWVAL[1] ? (~cap_dat[2] | (RWVAL[0] & ~cap_dat[1]) | level2) // Level 2 always ok + : (cap_dat[0] & ~prot_i & level2) ); // "normal" access + + // PTE access logic, normal state machine + // Updates to the PTEs are normal WRITE request to DRAM, therefore no MDONE at Write + + assign modi = ~CAPDAT[8] & WRITE & write_ok & ~icp_acc; // is "1" if the Modified Bit must be set + assign refer = CAPDAT[7] | do_zt; // Assumption "R" Bit is set if RDVAL/WRVAL and page border test + assign valid = (do_zt & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & cap_dat[0] & level1) + : (cap_dat[0] & ~prot_i); + + always @(posedge BCLK) mem_done <= MDONE & pte_acc; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) pstate <= 3'h0; + else + casex ({pte_go,mem_done,valid,refer,modi,pte_run_wr,pstate}) + 9'b0x_xxxx_000 : pstate <= 3'd0; // nothing to do + 9'b1x_xxxx_000 : pstate <= 3'd4; // start + 9'bx0_xxxx_100 : pstate <= 3'd4; // wait for Level 1 + 9'bx1_0xxx_100 : pstate <= 3'd0; // THAT'S ABORT ! + 9'bx1_11xx_100 : pstate <= 3'd6; // PTE Level 1 was referenced , next is Level 2 + 9'bx1_10xx_100 : pstate <= 3'd5; // for writing of modified Level 1 : R=1 + 9'bxx_xxx0_101 : pstate <= 3'd5; // write must wait + 9'bxx_xxx1_101 : pstate <= 3'd6; // one wait cycle + 9'bx0_xxxx_110 : pstate <= 3'd6; // wait for Level 2 + 9'bx1_0xxx_110 : pstate <= 3'd0; // THAT'S ABORT ! + 9'bx1_10xx_110 : pstate <= 3'd7; // Update neccesary : R=0 + 9'bx1_110x_110 : pstate <= 3'd0; // all ok - end + 9'bx1_111x_110 : pstate <= 3'd7; // Update neccesary : M=0 + 9'bxx_xxx0_111 : pstate <= 3'd7; // write must wait + 9'bxx_xxx1_111 : pstate <= 3'd0; // continues to end of DRAM write + default : pstate <= 3'd0; + endcase + + assign pte_acc = pstate[2]; + assign level1 = ~pstate[1]; + assign level2 = pstate[1]; + + assign valid_a = (ZTEST & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & ~cap_dat[0] & level1) + : ~cap_dat[0]; // not do_zt because of icp_acc in ABORT + + assign ABORT = mem_done & valid_a & ~icp_acc; + assign PROTECT = ((mem_done & prot_i & ~icp_acc) | PROT_ERROR) & ~(ZTEST & RWVAL[1]); // no Protection-Error at RDVAL/WRVAL + + assign IACC_STAT[1] = mem_done & ~cap_dat[0] & icp_acc; + assign IACC_STAT[2] = level1; + assign IACC_STAT[3] = mem_done & prot_i & icp_acc; + + assign ABO_LEVEL1 = level1; // is stored in case of ABORT in ADDR_UNIT + + assign rd_level2 = (pstate == 3'd5) | (mem_done & (pstate == 3'd4) & refer & valid); + + assign WR_MRAM = mem_done & (pstate == 3'd6) & valid & ~icp_acc & ~ZTEST; + assign wr_icmram = mem_done & (pstate == 3'd6) & valid & icp_acc; + + // Signals to the Instruction Cache + // pte_acc combined with icp_acc for STATISTIK. + assign IC_SIGS = {(pte_acc & icp_acc),wr_icmram}; + + assign PTE_MUX = pte_go | (pte_acc & ~pstate[1]); + + assign pte_puls = mem_done & pte_acc & ~pstate[1]; + assign PTE_STAT = {(pte_puls & icp_acc),(pte_puls & ~icp_acc)}; // only for statistic + + assign PD_MUX = ((pstate == 3'd4) & mem_done & valid & ~refer) // switch data-MUX, write level 1 too + | ((pstate == 3'd6) & mem_done & valid & (~refer | modi)) // write level 2 + | (((pstate == 3'd5) | (pstate == 3'd7)) & ~pte_run_wr); + + assign pte_wr_sig = ENWR & PD_MUX; + + always @(posedge BCLK) pte_run_wr <= pte_wr_sig; // Ok-Signal for pstate State-machine + + assign PKEEP = (pstate == 3'd6) | ((pstate == 3'd7) & ~pte_run_wr); // keep the DRAM address + + // If there is a PTE still in the data cache it must be deleted. If MMU Bits are set by the pte engine a following + // READ would deliver wrong data if cache hit. Therefore access of the Tags. + always @(posedge BCLK or negedge BRESET) + if (!BRESET) ko_state <= 3'b000; + else + casex ({kostart,ko_state}) + 4'b0_000 : ko_state <= 3'b000; + 4'b1_000 : ko_state <= 3'b110; + 4'bx_110 : ko_state <= 3'b111; + 4'bx_111 : ko_state <= 3'b100; + 4'bx_100 : ko_state <= 3'b000; + default : ko_state <= 3'b000; + endcase + + assign kostart = pte_go | rd_level2; + + // ko_state[2] suppresses ACC_OK at READ + assign run_dc = (~ko_state[2] | QWATWO) & ~dma_run; // Bugfix of 7.10.2015 + assign KOMUX = ko_state[1] | DMA_MUX; + assign KDET = ko_state[0] | dma_kdet; + + assign HIT_ALL = MMU_HIT & CA_HIT & run_dc & ~pte_acc; // for Update "Last-Set" , MMU_HIT contains ZUGRIFF + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) card_flag <= 1'b0; + else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE); + + assign CUPDATE = card_flag & USE_CA & MDONE; + + always @(posedge BCLK) rd_rdy <= card_flag & MDONE; + + // The cache RAM can not provide fast enough the data after an Update. In this case a secondary data path is activated + assign AUX_DAT = rd_rdy; + + // DRAM interface : + + always @(posedge BCLK) DRAM_WR <= wr_dram | pte_wr_sig; // pulse + always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1; + else + DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET; + // IO interface : + + always @(posedge BCLK) + begin + if (IO_ACC) IO_RD <= READ; else IO_RD <= IO_RD & ~IO_READY & BRESET; + if (IO_ACC) IO_WR <= WRITE; else IO_WR <= IO_WR & ~IO_READY & BRESET; + end + + assign io_busy = IO_RD | IO_WR | rd_done; // access is gone in next clock cycle, therefore blocked with "rd_done" + + always @(posedge BCLK) rd_done <= IO_RD & IO_READY; // For READ one clock later for data to come through + + assign dma = ICTODC[2]; // external request HOLD after FF in ICACHE + + always @(posedge BCLK) dma_run <= (dma_go | (dma_run & dma)) & BRESET; // stops the data access until HOLD becomes inactive + + assign HLDA = ~(ICTODC[1] & dma_run); // Signal for system that the CPU has stopped accesses + + always @(posedge BCLK) dma_kdet <= FILLRAM; + assign DMA_MUX = FILLRAM | dma_kdet; + + // global feedback to ADDR_UNIT, early feedback to Op-Dec : you can continue + + assign ACC_OK = ZTEST ? (~VIRTUELL | zt_ok) + : (IO_SPACE ? ((IO_ACC & WRITE) | rd_done) : (wr_dram | (READ & MMU_HIT & rd_ende & run_dc)) ); + + // PTB1 and PTB0 + + always @(posedge BCLK) if (PTB_WR && !PTB_SEL) ptb0 <= CPU_OUT[27:12]; + always @(posedge BCLK) if (PTB_WR && PTB_SEL) ptb1 <= CPU_OUT[27:12]; + + always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block + always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL; + + assign ptb10 = SEL_PTB1 ? ptb1 : ptb0; + + // Address multiplex between ICACHE=1 and DCACHE=0 : + always @(posedge BCLK) if (pte_go) icp_acc <= do_ic_p; + + assign pte_sel = pte_go ? do_ic_p : icp_acc; + + assign virtual_adr = pte_sel ? IC_VA : VADR_R; + + // The 2 Address-LSB's : no full access : USE_CA = 0 + assign PTE_ADR = rd_level2 ? {CAPDAT[27:12],virtual_adr[21:12],2'b00} : {ptb10,virtual_adr[31:22],2'b00}; + + // PTE_DAT[8] is used for update of MMU_RAM. + assign pte_dat_8 = (level2 & WRITE & write_ok & ~icp_acc) | CAPDAT[8]; + always @(posedge BCLK) pte_modi = pte_dat_8; + assign PTE_DAT = {4'h3,CAPDAT[15:9],pte_modi,1'b1,CAPDAT[6:0]}; // the top 4 bits are Byte-Enable + + // The data for the MMU-RAM : 24 Bits , [6]=Cache Inhibit + assign MMU_DIN = {pl_dat,pte_dat_8,CAPDAT[6],CAPDAT[31:12]}; + + // Protection field + + always @(posedge BCLK) if (mem_done && (pstate[2:0] == 3'd4)) prot_level1 <= cap_dat[2:1]; + + always @(prot_level1 or cap_dat) + casex ({prot_level1,cap_dat[2]}) + 3'b11_x : pl_dat = cap_dat[2:1]; + 3'b10_1 : pl_dat = 2'b10; + 3'b10_0 : pl_dat = cap_dat[2:1]; + 3'b01_1 : pl_dat = 2'b01; + 3'b01_0 : pl_dat = cap_dat[2:1]; + 3'b00_x : pl_dat = 2'b00; + endcase + + always @(USER or pl_dat) // is used if no PTE update is neccesary for M-Bit if writing is not allowed + casex ({USER,pl_dat}) + 3'b1_11 : write_ok = 1'b1; + 3'b0_1x : write_ok = 1'b1; + 3'b0_01 : write_ok = 1'b1; + default : write_ok = 1'b0; + endcase + + assign acc_level = level2 ? pl_dat : cap_dat[2:1]; + assign user_ptw = icp_acc ? ICTODC[3] : USER; + assign wr_ptw = ~icp_acc & (WRITE | RMW | (ZTEST & ~RWVAL[1])); // only data cache can write + + always @(acc_level or user_ptw or wr_ptw) + case (acc_level) + 2'b00 : prot_i = user_ptw | wr_ptw; + 2'b01 : prot_i = user_ptw; + 2'b10 : prot_i = user_ptw & wr_ptw; + 2'b11 : prot_i = 1'b0; + endcase + +endmodule + diff --git a/src/m32632/DATENPFAD.v b/src/m32632/DATENPFAD.v new file mode 100644 index 0000000..ada7fb4 --- /dev/null +++ b/src/m32632/DATENPFAD.v @@ -0,0 +1,412 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: DATENPFAD.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 7 October 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// DATENPFAD the data path of M32632 +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module DATENPFAD( BCLK, BRESET, WREN, IO_READY, LD_DIN, LD_IMME, WR_REG, IC_USER, ACC_FELD, ACC_STAT, DIN, DISP, IC_TEX, + IMME_Q, INFO_AU, LD_OUT, DETOIP, MMU_UPDATE, OPER, PC_ARCHI, PC_ICACHE, RDAA, RDAB, START, WMASKE, + WRADR, DONE, Y_INIT, WRITE_OUT, READ_OUT, ZTEST, RMW, QWATWO, ACC_DONE, REG_OUT, PTB_SEL, PTB_WR, ACB_ZERO, + ABORT, SAVE_PC, CFG, CINV, DP_Q, IVAR, MCR, PACKET, PC_NEW, PSR, SIZE, STRING, TRAPS, VADR, RWVFLAG, + DBG_HIT, DBG_IN, COP_GO, COP_OP, COP_IN, COP_DONE, COP_OUT); + +input BCLK; +input BRESET; +input WREN; // write enable of the register file +input IO_READY; +input LD_DIN; +input LD_IMME; +input WR_REG; // write signal for the DP_FPU +input IC_USER; +input RWVFLAG; +input [14:0] ACC_FELD; +input [5:0] ACC_STAT; +input [31:0] DIN; +input [31:0] DISP; +input [2:0] IC_TEX; +input [31:0] IMME_Q; +input [6:0] INFO_AU; +input [1:0] LD_OUT; +input [12:0] DETOIP; +input [1:0] MMU_UPDATE; +input [10:0] OPER; +input [31:0] PC_ARCHI; +input [31:0] PC_ICACHE; +input [7:0] RDAA; +input [7:0] RDAB; +input [1:0] START; +input [1:0] WMASKE; +input [5:0] WRADR; +input DBG_HIT; +input COP_DONE; +input [23:0] COP_OP; +input [63:0] COP_IN; + +output DONE; +output Y_INIT; +output WRITE_OUT; +output READ_OUT; +output ZTEST; +output RMW; +output QWATWO; +output ACC_DONE; +output REG_OUT; +output PTB_SEL; +output PTB_WR; +output reg ACB_ZERO; +output ABORT; +output SAVE_PC; +output [12:0] CFG; +output [3:0] CINV; +output [63:0] DP_Q; +output [1:0] IVAR; +output [3:0] MCR; +output [3:0] PACKET; +output [31:0] PC_NEW; +output [11:0] PSR; +output [1:0] SIZE; +output [4:0] STRING; +output [5:0] TRAPS; +output [31:0] VADR; +output [40:2] DBG_IN; +output COP_GO; +output [127:0] COP_OUT; + +reg [31:0] high_dq; +reg [31:0] OUT_I; +reg [31:0] BYDIN; // the bypass register + +wire [2:0] BITSEL; +wire [1:0] BWD; +wire CLR_LSB; +wire [31:0] ERGEBNIS; // the result bus +wire FL; +wire [31:0] FSR; +wire [63:0] MRESULT; +wire [7:0] OPCODE; +wire SELI_A; +wire SELI_B; +wire [2:0] SP_CMP; +wire [31:0] SRC1; // the bus for the Source 1 operand +wire [31:0] SRC2; // the bus for the Source 2 operand +wire [4:0] TT_DP; +wire TWREN; // active if FPU Trap occurs +wire UP_DP; +wire WRADR_0; +wire WREN_L,WREN_LX; +wire LD_FSR; +wire UP_SP; +wire [4:0] TT_SP; +wire [31:0] addr_i; +wire [2:0] DP_CMP; +wire [31:0] DP_OUT; +wire [31:0] SFP_DAT; +wire ld_out_l; +wire [6:0] BMCODE; +wire [31:0] OUT_A,OUT_B; +wire SP_MUX; +wire [31:0] I_OUT; +wire [31:0] FP_OUT; +wire DOWR; +wire [31:0] DEST1,DEST2; +wire ENWR; +wire [3:0] OVF_BCD; +wire [3:0] DSR; +wire acb_zero_i; +wire [31:0] BMASKE; + +assign FL = OPER[10]; +assign BWD = OPER[9:8]; +assign OPCODE = OPER[7:0]; + +assign ERGEBNIS = SP_MUX ? FP_OUT : I_OUT; + +assign WRADR_0 = WRADR[0] ^ CLR_LSB; +assign ENWR = WREN_L | WREN; +assign DOWR = ENWR & TWREN; + +assign WREN_L = WREN_LX & ~TRAPS[0]; + +assign DP_Q[63:32] = high_dq; + +assign PC_NEW = SRC1; + +always @(posedge BCLK) if (LD_OUT[1] || WREN) ACB_ZERO <= acb_zero_i; + +always @(posedge BCLK) if (LD_OUT[1] || ld_out_l) high_dq <= ERGEBNIS; + +always @(posedge BCLK) if (LD_DIN) OUT_I <= LD_IMME ? IMME_Q : DIN; + +always @(posedge BCLK) if (RDAA[7]) BYDIN <= ERGEBNIS; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Register Set 1 => SRC1 +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +REGISTER REG_SET_A( + .BCLK(BCLK), + .ENWR(ENWR), + .DOWR(DOWR), + .DIN(ERGEBNIS), + .BYDIN(BYDIN), + .RADR(RDAA), + .WADR({WRADR[5:1],WRADR_0}), + .WMASKE(WMASKE), + .SELI(SELI_A), + .DOUT(OUT_A)); + +assign SRC1 = SELI_A ? OUT_I : OUT_A; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Register Set 2 => SRC2 +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +REGISTER REG_SET_B( + .BCLK(BCLK), + .ENWR(ENWR), + .DOWR(DOWR), + .DIN(ERGEBNIS), + .BYDIN(BYDIN), + .RADR(RDAB), + .WADR({WRADR[5:1],WRADR_0}), + .WMASKE(WMASKE), + .SELI(SELI_B), + .DOUT(OUT_B)); + +assign SRC2 = SELI_B ? OUT_I : OUT_B; + +MULFILTER M_FILTER( + .FLOAT(OPCODE[2]), + .BWD(BWD), + .SRC1(SRC1), + .SRC2(SRC2), + .DEST1(DEST1), + .DEST2(DEST2)); + +SIGNMUL S_MULTI( // signed multiplier 32 * 32 bits = 64 bits + .dataa(DEST1), + .datab(DEST2), + .result(MRESULT)); + +BITMASK BITM_U( + .AA(BMCODE), + .DOUT(BMASKE)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The integer data path +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +I_PFAD GANZ_U( + .FL(FL), + .BRESET(BRESET), + .BCLK(BCLK), + .WREN(WREN), + .LD_OUT(LD_OUT[1]), + .ADDR(addr_i), + .BITSEL(BITSEL), + .BMASKE(BMASKE), + .BWD(BWD), + .DP_CMP(DP_CMP), + .DP_OUT(DP_OUT), + .FSR(FSR), + .DETOIP(DETOIP[11:0]), + .MRESULT(MRESULT), + .OPCODE(OPCODE), + .RDAA(RDAA), + .SFP_DAT(SFP_DAT), + .SP_CMP(SP_CMP), + .SRC1(SRC1), + .SRC2(SRC2), + .WRADR(WRADR), + .DSR(DSR), + .OV_FLAG(TRAPS[2]), + .ACB_ZERO(acb_zero_i), + .BMCODE(BMCODE), + .I_OUT(I_OUT), + .PSR(PSR), + .STRING(STRING), + .OVF_BCD(OVF_BCD), + .DISP(DISP[4:0]), + .RWVFLAG(RWVFLAG)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The address unit +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +ADDR_UNIT ADDR_U( + .BCLK(BCLK), + .BRESET(BRESET), + .IO_READY(IO_READY), + .READ(ACC_FELD[11]), + .WRITE(ACC_FELD[10]), + .CLRMSW(ACC_FELD[2]), + .FULLACC(ACC_FELD[8]), + .POST(ACC_FELD[3]), + .DISP_OK(INFO_AU[0]), + .LDEA(ACC_FELD[9]), + .NEWACC(ACC_FELD[14]), + .FPU_TRAP(TRAPS[0]), + .ADIVAR(INFO_AU[2]), + .RWVAL_1(INFO_AU[3]), + .ABO_STAT({INFO_AU[1],IC_USER}), + .ACC_STAT(ACC_STAT), + .ASIZE(ACC_FELD[13:12]), + .BWD(BWD), + .DISP(DISP), + .IC_TEX(IC_TEX), + .INDEX(ACC_FELD[7:4]), + .MMU_UPDATE(MMU_UPDATE), + .PC_ARCHI(PC_ARCHI), + .PC_ICACHE(PC_ICACHE), + .SRC1(SRC1), + .SRC2(SRC2), + .SRC2SEL(ACC_FELD[1:0]), + .REG_OUT(REG_OUT), + .ACC_DONE(ACC_DONE), + .READ_OUT(READ_OUT), + .WRITE_OUT(WRITE_OUT), + .ABORT(ABORT), + .ADDR(addr_i), + .BITSEL(BITSEL), + .PACKET(PACKET), + .SIZE(SIZE), + .VADR(VADR), + .ZTEST(ZTEST), + .RMW(RMW), + .QWATWO(QWATWO), + .OP_RMW(INFO_AU[4]), + .PHASE_17(INFO_AU[5]), + .NO_TRAP(INFO_AU[6]) ); + +CONFIG_REGS CFG_DBG( + .BCLK(BCLK), + .BRESET(BRESET), + .WREN(WREN), + .LD_OUT(LD_OUT[1]), + .OPCODE(OPCODE), + .SRC1(SRC1), + .WRADR(WRADR), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .CFG(CFG), + .CINV(CINV), + .IVAR(IVAR), + .Y_INIT(Y_INIT), + .MCR(MCR), + .DBG_TRAPS(TRAPS[5:3]), + .PC_ARCHI(PC_ARCHI), + .DSR(DSR), + .USER(PSR[8]), + .PCMATCH(DETOIP[12]), + .DBG_IN(DBG_IN), + .DBG_HIT(DBG_HIT), + .READ(READ_OUT) ); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The long operation unit +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +DP_FPU DOUBLE_U( + .BCLK(BCLK), + .FL(FL), + .BRESET(BRESET), + .LD_LDQ(LD_OUT[0]), + .WR_REG(WR_REG), + .BWD(BWD), + .FSR(FSR[8:3]), + .OPCODE(OPCODE), + .SRC1(SRC1), + .SRC2(SRC2), + .START(START), + .DONE(DONE), + .UP_DP(UP_DP), + .WREN_L(WREN_LX), + .CLR_LSB(CLR_LSB), + .LD_OUT_L(ld_out_l), + .DVZ_TRAP(TRAPS[1]), + .DP_CMP(DP_CMP), + .DP_OUT(DP_OUT), + .DP_Q(DP_Q[31:0]), + .TT_DP(TT_DP), + .CY_IN(PSR[0]), + .OVF_BCD(OVF_BCD), + .COP_DONE(COP_DONE), + .COP_OP(COP_OP), + .COP_IN(COP_IN), + .COP_GO(COP_GO), + .COP_OUT(COP_OUT)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The single precision floating point unit +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//SP_FPU SINGLE_U( +// .FL(FL), +// .BCLK(BCLK), +// .BWD(BWD), +// .FSR(FSR[8:3]), +// .MRESULT(MRESULT[47:0]), +// .OPCODE(OPCODE), +// .SRC1(SRC1), +// .SRC2(SRC2), +// .LD_FSR(LD_FSR), +// .SP_MUX(SP_MUX), +// .UP_SP(UP_SP), +// .FP_OUT(FP_OUT), +// .I_OUT(SFP_DAT), +// .SP_CMP(SP_CMP), +// .TT_SP(TT_SP)); + + assign FP_OUT = 32'b0; + assign SFP_DAT = 32'b0; + assign TT_SP = 5'b0; + assign SP_CMP = 3'b0; + assign SP_MUX = 1'b0; + assign LD_FSR = 1'b0; + assign UP_SP = 1'b0; + +FP_STAT_REG FPS_REG( + .BCLK(BCLK), + .BRESET(BRESET), + .LFSR(LD_FSR), + .WREN(ENWR), + .WRADR(WRADR[5:4]), + .UP_DP(UP_DP), + .UP_SP(UP_SP & LD_OUT[1]), + .DIN(SRC1[16:0]), + .TT_DP(TT_DP), + .TT_SP(TT_SP), + .FPU_TRAP(TRAPS[0]), + .TWREN(TWREN), + .SAVE_PC(SAVE_PC), + .FSR(FSR)); + +endmodule diff --git a/src/m32632/DCACHE.v b/src/m32632/DCACHE.v new file mode 100644 index 0000000..f2b3ad3 --- /dev/null +++ b/src/m32632/DCACHE.v @@ -0,0 +1,500 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: DCACHE.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 7 October 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// DCACHE the data cache of M32632 +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module DCACHE( BCLK, MCLK, WRCFG, MDONE, BRESET, PTB_WR, PTB_SEL, IO_READY, REG_OUT, PSR_USER, WRITE, READ, RMW, QWATWO, + WAMUX, ENWR, IC_PREQ, FILLRAM, CFG, CINVAL, DMA_AA, DP_Q, DRAM_Q, IC_VA, ICTODC, IO_Q, IVAR, MCR_FLAGS, + PACKET, SIZE, VADR, WADDR, WCTRL, IO_RD, IO_WR, DRAM_ACC, DRAM_WR, INIT_RUN, PTE_STAT, KDET, HLDA, + ACC_STAT, DP_DI, DRAM_A, DRAM_DI, IACC_STAT, IC_SIGS, IO_A, IO_BE, IO_DI, KOLLI_A, MMU_DIN, ZTEST, + RWVAL, RWVFLAG, DBG_IN, DBG_HIT, ENDRAM ); + +input BCLK; +input MCLK; +input WRCFG; +input MDONE; +input BRESET; +input PTB_WR; +input PTB_SEL; +input IO_READY; +input REG_OUT; +input PSR_USER; +input WRITE; +input READ; +input ZTEST; +input RMW; +input QWATWO; +input WAMUX; +input ENWR; +input IC_PREQ; +input FILLRAM; +input [1:0] CFG; +input [1:0] CINVAL; +input [27:4] DMA_AA; +input [63:0] DP_Q; +input [31:0] DRAM_Q; +input [31:12] IC_VA; +input [3:0] ICTODC; +input [31:0] IO_Q; +input [1:0] IVAR; +input [3:0] MCR_FLAGS; +input [3:0] PACKET; +input [1:0] SIZE; +input [31:0] VADR; +input [11:2] WADDR; +input [2:0] WCTRL; +input [2:0] RWVAL; +input [40:2] DBG_IN; +input ENDRAM; + +output IO_RD; +output IO_WR; +output DRAM_ACC; +output DRAM_WR; +output INIT_RUN; +output [1:0] PTE_STAT; +output KDET; +output HLDA; +output RWVFLAG; +output [5:0] ACC_STAT; +output [31:0] DP_DI; +output [3:1] IACC_STAT; +output [1:0] IC_SIGS; +output [27:4] KOLLI_A; +output [23:0] MMU_DIN; +output reg [27:0] DRAM_A; +output reg [35:0] DRAM_DI; +output reg [31:0] IO_A; +output reg [3:0] IO_BE; +output reg [31:0] IO_DI; +output DBG_HIT; + +reg [31:0] DFFE_IOR; +reg [31:0] CAPDAT; +reg [31:0] VADR_R; +reg AUX_ALT; +reg DFF_QWEXT; + +wire [27:4] ADDR; +wire ADR_EQU; +wire AUX_DAT; +wire CA_HIT; +wire CA_SET; +wire CUPDATE; +wire DMA_MUX; +wire [3:0] ENBYTE; +wire HIT_ALL; +wire INIT_CA_RUN; +wire IO_ACC; +wire IO_SPACE; +wire KOMUX; +wire MMU_HIT; +wire NEW_PTB; +wire PTB_ONE; +wire [27:0] PTE_ADR; +wire [31:12] RADR; +wire [11:4] TAGA; +wire [23:0] UPDATE_C; +wire [31:0] UPDATE_M; +wire USE_CA; +wire USER; +wire WB_ACC; +wire WEMV; +wire WR_MRAM; +wire [31:0] WRDATA; +wire VIRT_A; +wire PTE_MUX; +wire WE_CV; +wire [23:0] DAT_CV; +wire [4:0] WADR_CV; +wire WRSET0; +wire [3:0] BE_SET; +wire [31:0] DAT_SET; +wire [9:0] A_SET; +wire WRSET1; +wire SEL_PTB1; +wire CI; +wire [27:0] ADR_MX; +wire LD_DRAM_A; +wire VIRTUELL; +wire NEW_PTB_RUN; +wire KILL; +wire LAST_MUX; +wire [31:0] SET_DAT; +wire [31:0] ALT_DAT; +wire [31:0] DAT_MV; +wire [3:0] RADR_MV; +wire [3:0] WADR_MV; +wire [31:0] LAST_DAT; +wire WRCRAM0; +wire WRCRAM1; +wire PROT_ERROR; +wire AUX_QW; +wire PD_MUX; +wire [19:0] PTE_DAT; +wire PKEEP; + +// +++++++++++++++++++ Memories ++++++++++++++++++++ + +reg [7:0] DATA0_D [0:1023]; // Data Set 0 : 4 kBytes +reg [7:0] DATA0_C [0:1023]; +reg [7:0] DATA0_B [0:1023]; +reg [7:0] DATA0_A [0:1023]; +reg [31:0] SET_DAT0; + +reg [7:0] DATA1_D [0:1023]; // Data Set 1 : 4 kBytes +reg [7:0] DATA1_C [0:1023]; +reg [7:0] DATA1_B [0:1023]; +reg [7:0] DATA1_A [0:1023]; +reg [31:0] SET_DAT1; + +reg [15:0] TAGSET_0 [0:255]; // Tag Set for Data Set 0 : 256 entries of 16 bits +reg [15:0] TAG0; + +reg [15:0] TAGSET_1 [0:255]; // Tag Set for Data Set 1 : 256 entries of 16 bits +reg [15:0] TAG1; + +reg [23:0] CA_VALID [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits +reg [23:0] CVALID; + +reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits +reg [35:0] MMU_Q; + +reg [31:0] MMU_VALID [0:15]; // Valid bits for MMU Tag Set : 16 entries of 32 bits +reg [31:0] MVALID; + +assign ADR_EQU = ({RADR[27:12],VADR_R[11:4]} == DRAM_A[27:4]); // Limited to 256 MB + +assign ALT_DAT = AUX_ALT ? DFFE_IOR : CAPDAT ; + +assign RADR = VIRT_A ? MMU_Q[19:0] : VADR_R[31:12] ; + +assign ADR_MX = PTE_MUX ? PTE_ADR : {RADR[27:12],VADR_R[11:2],USE_CA,CA_SET} ; + +assign KOLLI_A = DMA_MUX ? DMA_AA : DRAM_A[27:4] ; + +assign SET_DAT = CA_SET ? SET_DAT1 : SET_DAT0 ; + +assign VIRT_A = ~CINVAL[0] & VIRTUELL; + +assign USER = ~MCR_FLAGS[3] & PSR_USER; + +assign DAT_SET = WRITE ? WRDATA : DRAM_Q ; + +assign BE_SET = ENBYTE | {~WRITE,~WRITE,~WRITE,~WRITE}; + +assign ADDR = KDET ? KOLLI_A : {RADR[27:12],VADR_R[11:4]} ; + +assign A_SET = WAMUX ? WADDR : VADR_R[11:2] ; + +assign TAGA = KOMUX ? KOLLI_A[11:4] : VADR[11:4] ; + +assign INIT_RUN = NEW_PTB_RUN | INIT_CA_RUN; + +assign LAST_MUX = AUX_ALT | AUX_DAT | AUX_QW; + +assign LAST_DAT = LAST_MUX ? ALT_DAT : SET_DAT ; + +assign LD_DRAM_A = ~(DRAM_ACC | PKEEP); + +assign ACC_STAT[4] = IO_ACC; +assign ACC_STAT[5] = CA_HIT; + +always @(posedge BCLK) + if (IO_ACC) + begin + IO_BE <= ENBYTE; + IO_DI <= WRDATA; + IO_A <= {RADR[31:12],VADR_R[11:0]}; + end + +always @(posedge BCLK) if (LD_DRAM_A) DRAM_A[27:0] <= ADR_MX[27:0]; + +always @(posedge BCLK) if (IO_RD) DFFE_IOR <= IO_Q; + +always @(posedge BCLK) + begin + DRAM_DI <= {(PD_MUX ? PTE_DAT[19:16] : ENBYTE),WRDATA[31:16], + (PD_MUX ? PTE_DAT[15:0] : WRDATA[15:0])}; + AUX_ALT <= DFF_QWEXT | IO_RD; + DFF_QWEXT <= IO_RD & SIZE[0] & SIZE[1]; + VADR_R <= VADR; + end + +always @(posedge MCLK) if (WCTRL[2]) CAPDAT <= DRAM_Q; + +// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++ + +always @(posedge BCLK) CVALID <= CA_VALID[TAGA[11:7]]; + +always @(negedge BCLK) if (WE_CV) CA_VALID[WADR_CV] <= DAT_CV; + +// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++ + +always @(posedge BCLK) TAG0 <= TAGSET_0[TAGA]; + +always @(negedge BCLK) if (WRCRAM0) TAGSET_0[VADR_R[11:4]] <= RADR[27:12]; + +// +++++++++++++++++++++++++ Tag Set 1 +++++++++++++++++++++ + +always @(posedge BCLK) TAG1 <= TAGSET_1[TAGA]; + +always @(negedge BCLK) if (WRCRAM1) TAGSET_1[VADR_R[11:4]] <= RADR[27:12]; + +// +++++++++++++++++++++++++ Data Set 0 ++++++++++++++++++++ + +always @(posedge BCLK) + begin + SET_DAT0[31:24] <= DATA0_D[VADR[11:2]]; + SET_DAT0[23:16] <= DATA0_C[VADR[11:2]]; + SET_DAT0[15:8] <= DATA0_B[VADR[11:2]]; + SET_DAT0[7:0] <= DATA0_A[VADR[11:2]]; + end + +always @(posedge MCLK) + if (WRSET0) + begin + if (BE_SET[3]) DATA0_D[A_SET] <= DAT_SET[31:24]; + if (BE_SET[2]) DATA0_C[A_SET] <= DAT_SET[23:16]; + if (BE_SET[1]) DATA0_B[A_SET] <= DAT_SET[15:8]; + if (BE_SET[0]) DATA0_A[A_SET] <= DAT_SET[7:0]; + end + +// +++++++++++++++++++++++++ Data Set 1 ++++++++++++++++++++ + +always @(posedge BCLK) + begin + SET_DAT1[31:24] <= DATA1_D[VADR[11:2]]; + SET_DAT1[23:16] <= DATA1_C[VADR[11:2]]; + SET_DAT1[15:8] <= DATA1_B[VADR[11:2]]; + SET_DAT1[7:0] <= DATA1_A[VADR[11:2]]; + end + +always @(posedge MCLK) + if (WRSET1) + begin + if (BE_SET[3]) DATA1_D[A_SET] <= DAT_SET[31:24]; + if (BE_SET[2]) DATA1_C[A_SET] <= DAT_SET[23:16]; + if (BE_SET[1]) DATA1_B[A_SET] <= DAT_SET[15:8]; + if (BE_SET[0]) DATA1_A[A_SET] <= DAT_SET[7:0]; + end + +DCACHE_SM DC_SM( + .BCLK(BCLK), + .BRESET(BRESET), + .VIRTUELL(VIRTUELL), + .IO_SPACE(IO_SPACE), + .MDONE(MDONE), + .MMU_HIT(MMU_HIT), + .CA_HIT(CA_HIT), + .READ(READ), + .WRITE(WRITE), + .ZTEST(ZTEST), + .RMW(RMW), + .QWATWO(QWATWO), + .USE_CA(USE_CA), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .SEL_PTB1(SEL_PTB1), + .IO_READY(IO_READY), + .USER(USER), + .PROTECT(ACC_STAT[3]), + .PROT_ERROR(PROT_ERROR), + .ENWR(ENWR), + .WB_ACC(WB_ACC), + .ADR_EQU(ADR_EQU), + .IC_PREQ(IC_PREQ), + .CAPDAT(CAPDAT[31:0]), + .CPU_OUT(DP_Q[59:44]), + .FILLRAM(FILLRAM), + .IC_VA(IC_VA), + .ICTODC(ICTODC), + .VADR_R(VADR_R[31:12]), + .NEW_PTB(NEW_PTB), + .PTB_ONE(PTB_ONE), + .DRAM_ACC(DRAM_ACC), + .DRAM_WR(DRAM_WR), + .IO_ACC(IO_ACC), + .IO_RD(IO_RD), + .IO_WR(IO_WR), + .PTE_STAT(PTE_STAT), + .ABORT(ACC_STAT[1]), + .WR_MRAM(WR_MRAM), + .CUPDATE(CUPDATE), + .AUX_DAT(AUX_DAT), + .PTE_MUX(PTE_MUX), + .ACC_OK(ACC_STAT[0]), + .ABO_LEVEL1(ACC_STAT[2]), + .IACC_STAT(IACC_STAT), + .KOMUX(KOMUX), + .KDET(KDET), + .HIT_ALL(HIT_ALL), + .DMA_MUX(DMA_MUX), + .HLDA(HLDA), + .RWVAL(RWVAL[1:0]), + .RWVFLAG(RWVFLAG), + .IC_SIGS(IC_SIGS), + .MMU_DIN(MMU_DIN), + .PD_MUX(PD_MUX), + .PKEEP(PKEEP), + .PTE_ADR(PTE_ADR), + .PTE_DAT(PTE_DAT)); + +CA_MATCH DCA_COMPARE( + .INVAL_L(CINVAL[0]), + .CI(CI), + .MMU_HIT(MMU_HIT), + .WRITE(WRITE), + .KDET(KDET), + .ADDR(ADDR), + .CFG(CFG), + .ENDRAM(ENDRAM), + .CVALID(CVALID), + .TAG0(TAG0), + .TAG1(TAG1), + .CA_HIT(CA_HIT), + .CA_SET(CA_SET), + .WB_ACC(WB_ACC), + .USE_CA(USE_CA), + .IOSEL(RADR[31:28]), + .IO_SPACE(IO_SPACE), + .KILL(KILL), + .DC_ILO(RWVAL[2]), + .UPDATE(UPDATE_C)); + +DCA_CONTROL DCA_CTRL( + .BCLK(BCLK), + .MCLK(MCLK), + .BRESET(BRESET), + .CA_SET(CA_SET), + .HIT_ALL(HIT_ALL), + .UPDATE(UPDATE_C), + .VADR_R(ADDR[11:7]), + .DRAM_ACC(DRAM_ACC), + .CUPDATE(CUPDATE), + .KILL(KILL), + .WRITE(WRITE), + .WRCFG(WRCFG), + .WCTRL(WCTRL[1:0]), + .INVAL_A(CINVAL[1]), + .DAT_CV(DAT_CV), + .WADR_CV(WADR_CV), + .WE_CV(WE_CV), + .INIT_CA_RUN(INIT_CA_RUN), + .WRCRAM0(WRCRAM0), + .WRCRAM1(WRCRAM1), + .WRSET0(WRSET0), + .WRSET1(WRSET1)); + +MMU_MATCH MMU_COMPARE( + .USER(USER), + .WRITE(WRITE), + .READ(READ), + .RMW(RMW), + .IVAR(IVAR), + .MCR_FLAGS(MCR_FLAGS[2:0]), + .MMU_VA(MMU_Q[35:20]), + .MVALID(MVALID), + .VADR_R(VADR_R[31:12]), + .MMU_HIT(MMU_HIT), + .PROT_ERROR(PROT_ERROR), + .VIRTUELL(VIRTUELL), + .CI(CI), + .SEL_PTB1(SEL_PTB1), + .UPDATE(UPDATE_M)); + +MMU_UP MMU_CTRL( + .BCLK(BCLK), + .BRESET(BRESET), + .NEW_PTB(NEW_PTB), + .IVAR(IVAR[1]), + .PTB1(PTB_ONE), + .WR_MRAM(WR_MRAM), + .MVALID(MVALID), + .UPDATE(UPDATE_M), + .VADR(VADR[19:16]), + .VADR_R(VADR_R[19:16]), + .WE_MV(WEMV), + .NEW_PTB_RUN(NEW_PTB_RUN), + .DAT_MV(DAT_MV), + .RADR_MV(RADR_MV), + .WADR_MV(WADR_MV)); + +// +++++++++++++++++++++++++ MMU Valid +++++++++++++++++++++ + +always @(posedge BCLK) MVALID <= MMU_VALID[RADR_MV]; + +always @(negedge BCLK) if (WEMV) MMU_VALID[WADR_MV] <= DAT_MV; + +// +++++++++++++++++++++++++ MMU Tags ++++++++++++++++++++++ + +always @(posedge BCLK) MMU_Q <= MMU_TAGS[VADR[19:12]]; + +always @(negedge BCLK) if (WR_MRAM) MMU_TAGS[VADR_R[19:12]] <= {VADR_R[31:20],MMU_DIN[23:0]}; + +RD_ALIGNER RD_ALI( + .BCLK(BCLK), + .ACC_OK(ACC_STAT[0]), + .REG_OUT(REG_OUT), + .PACKET(PACKET), + .RDDATA(LAST_DAT), + .SIZE(SIZE), + .CA_HIT(CA_HIT), + .DP_DI(DP_DI), + .AUX_QW(AUX_QW)); + +WR_ALIGNER WR_ALI( + .DP_Q(DP_Q), + .PACKET(PACKET), + .SIZE(SIZE), + .ENBYTE(ENBYTE), + .WRDATA(WRDATA)); + +DEBUG_AE DBGAE( + .DBG_IN(DBG_IN), + .READ(READ), + .WRITE(WRITE), + .USER(USER), + .VIRTUELL(VIRTUELL), + .ACC_OK(ACC_STAT[0]), + .VADR_R(VADR_R[31:2]), + .MMU_Q(MMU_Q[19:0]), + .ENBYTE(ENBYTE), + .DBG_HIT(DBG_HIT)); + +endmodule diff --git a/src/m32632/DECODER.v b/src/m32632/DECODER.v new file mode 100644 index 0000000..0d993af --- /dev/null +++ b/src/m32632/DECODER.v @@ -0,0 +1,1755 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: DECODER.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 21 January 2016 +// +// Copyright (C) 2016 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// DECODER Instruction Decoding and Flow Control +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module DECODER ( BCLK, BRESET, INT_N, NMI_N, ANZ_VAL, OPREG, CFG, PSR, ACC_DONE, DC_ABORT, IC_ABORT, ACB_ZERO, DONE, + PC_SAVE, STRING, INIT_DONE, ILL, UNDEF, TRAPS, IC_READ, STOP_CINV, + GENSTAT, DISP, IMME_Q, DISP_BR, USED, NEW, LOAD_PC, NEXT_PCA, RDAA, RDAB, OPER, START, LD_OUT, LD_DIN, LD_IMME, + INFO_AU, ACC_FELD, WREN, WRADR, WMASKE, WR_REG, DETOIP, MMU_UPDATE, RESTART, STOP_IC, RWVAL, ENA_HK, ILO, COP_OP ); + + input BCLK,BRESET; + input INT_N,NMI_N; // external inputs + input [2:0] ANZ_VAL; + input [55:0] OPREG; // the OPREG contains the bytes to decode, OPREG[55:32] are don't care + input [8:0] CFG; // CONFIG : many bits are don't-care + input [11:0] PSR; + input ACC_DONE; + input DC_ABORT,IC_ABORT; + input ACB_ZERO; + input DONE; + input [31:0] PC_SAVE; + input [4:0] STRING; + input INIT_DONE; + input ILL,UNDEF; + input [5:0] TRAPS; + input IC_READ; + input STOP_CINV; // not to mix it up with STOP_IC + + output [2:0] GENSTAT; + output [31:0] DISP,IMME_Q,DISP_BR; // three main data busses : Displacement, Immediate and Displacement for Branch + output [2:0] USED; + output NEW; + output LOAD_PC; + output NEXT_PCA; + output [7:0] RDAA,RDAB; + output [10:0] OPER; + output [1:0] START,LD_OUT; + output LD_DIN,LD_IMME; + output [6:0] INFO_AU; + output [14:0] ACC_FELD; + output WREN; + output [5:0] WRADR; + output [1:0] WMASKE; + output reg WR_REG; + output [12:0] DETOIP; + output [1:0] MMU_UPDATE; + output RESTART; + output STOP_IC; + output [2:0] RWVAL; + output ENA_HK; + output reg ILO; + output [23:0] COP_OP; + + reg [31:0] DISP,disp_val; + reg [10:0] oper_i; + reg [2:0] USED; + reg [14:0] ACC_FELD; + reg [1:0] ldoreg; + reg wren_i; + reg [5:0] wradr_i; + reg [1:0] wmaske_i; + reg [1:0] START; + reg [23:0] COP_OP; + reg spupd_i; + reg [3:0] disp_sel; + reg [52:0] op1_feld; + reg [47:0] op2_feld; + reg [47:0] op3_feld; + reg [47:0] op_feld_reg; + reg [31:0] imme_i; + reg [2:0] valid; + reg [7:0] phase_reg; + reg [3:0] di_stat; // Displacement Status + reg [3:0] cc_feld; + reg [1:0] ex_br_op; + reg acb_reg; + reg jsr_flag; + reg [8:0] waitop,wait_reg; + reg branch; + reg [3:0] dim_feld; + reg [66:0] new_op; + reg short_op_reg; + reg [15:0] idx_reg; + reg [35:0] gen_src1; + reg [33:0] gen_src2; + reg qw_flag; + reg long_reg; + reg new_spsel; + reg s_user,old_su; + reg [1:0] stack_sel; // Stack select for USER and SUPERVISOR + reg [1:0] s_mod; // Modifier for Stack select + reg upd_info,dw_info; + reg [2:0] rpointer; + reg [5:0] resto; // for RESTORE + reg init_rlist; + reg new_fp; + reg format1; + reg ldpc_phase; + reg reti_flag; + reg no_t2p; + reg iabort,ia_save; + reg mmu_sel; + reg [1:0] nmi_reg; + reg nmi_flag,int_flag; + reg type_nmi; + reg [3:0] exc_vector; + reg phase_exc; + reg [3:0] ovf_pipe; + reg dbg_s,dbg_trap,dbg_en,addr_cmp; + reg ssrc_flag,sdest_flag; + reg op_setcfg,setcfg_lsb; + reg inss_op; + reg exin_cmd,extract; // EXT/INS + reg bit_reg; // Flag for Bit opcodes : Source2 = Reg + reg kurz_st; // Flag for MOVM/CMPM + reg kill_opt; // Flag for optimized MOVS + reg cmps_flag; // Flag for CMPS + reg skps_flag; // Flag for SKPS + reg mt_flag; // Flag for Match and Translate + reg spu_block; // block of SP update at Long operation + reg dia_op,dia_flag; // Flag for DIA + reg m_ussu,m_usel,dc_user; // MOVUS/SU + reg rwval_flag,wrval_flag; // RDVAL/WRVAL + reg cinv_flag; // Flag for CINV + reg [5:0] lmrreg; + reg no_init,a_ivar; + reg index_cmd; + reg stop_d; + reg dc_ilo; + + wire PHASE_0; + wire [7:0] phase_ein; // Phase after ABORT has changed the content to 0 + wire de_flag,ivec_flag; + wire next; + wire [18:0] new_addr,pop_fp,save_pc; + wire [13:0] new_regs; + wire [7:0] new_ph,ppfp; + wire [7:0] new_nx; + wire op_1byte,op_12byte,op_2byte,op_3byte; + wire jump; + wire short_op,short_def; + wire acb_op,acb_flag; + wire zero,carry_psr,negativ,larger,flag; + wire valid_size; + wire op_ok; + wire stop; + wire [47:0] opc_bits; + wire [47:0] op_feld; + wire [2:0] atys,atyd; + wire [3:0] auop_s,auop_d; + wire long,src2_flag,dest_flag; + wire [6:0] src_1,src_2,src_1l,src_2l; + wire [1:0] src1_le,src2_le; + wire acc1,acc2; + wire spupd; + wire [6:0] saver; // for SAVE + wire [2:0] reg_nr; + wire save_reg; + wire ld_disp,disp_ok; + wire store_pc; + wire do_xor; + wire do_long; + wire [1:0] idx_n,n_idx; + wire idx; + wire [1:0] otype; + wire [10:0] opera,op_str,op_sho; + wire [5:0] dest_r,dest_rl; + wire phase_idx; + wire [15:0] idx_bytes,idx_feld; + wire [3:0] idx_1,idx_2; + wire [4:0] src1_addr,src2_addr; + wire [6:0] usp_1,usp_2; + wire [33:0] tos_oper; + wire [18:0] adrd1,exr11,exr12,adrd2,adwr2,exr22,exw22,re_wr,st_src,st_src2,st_dest,st_len,st_trde,st_trs2; + wire [7:0] phrd1,phrd2,phwr2; + wire [6:0] rega1,irrw1,rega2,irrw2; + wire [3:0] nxrd1,nxrw2; + wire rmw; + wire [6:0] quei1,quet1; // Registeradr + wire [7:0] endea,goacb,dowait; // Phase + wire [3:0] diacb; // DIMM access + wire qword; + wire [6:0] stack,no_modul,ttstak; + wire [12:0] pop_1; + wire mpoi_1,mpoi_2; + wire [1:0] src1_tos; // the code for REUSE is 2'b11 + wire svc_flag,bpt_flag,flag_flag,trac_flag; + wire [3:0] misc_vectors; + wire [2:0] psr_code; + wire exception; + wire interrupt; + wire abort; // DC_ABORT | iabort; + wire abo_int; + wire iabo_fall; + wire abbruch,fpu_trap,dvz_trap; + wire abbruch2; + wire dbg_flag; + wire ovf_op,ovf2_op,ovf_flag; + wire pc_match; + wire no_trap; + wire [10:0] op_psr,op_scp; + wire [30:0] ai_next; + wire set_src,set_dest,clr_sflag; + wire [7:0] rrepa; // Repair Phase of Abort for String opcodes + wire [7:0] ph_str; // working phase String + wire ph_match; + wire t2p; + wire rw_bit,op_ilo; + wire setcfg; + wire string_ende; + wire wlor; // Flag to generate WR_REG signal + wire [5:0] wstr0,wstr1,wstr2; + wire [6:0] rstr0,rstr1,rstr2; + wire rett_exc; + wire chk_rmw; + + // Variables for 2- and 3-Byte Dekoder : + reg [5:0] hzr_c; // CASE Statement + wire [1:0] hzl_a; + wire [2:0] hzl_b; + wire [5:0] hzr_a,hzr_b,hzr_s; + wire hdx_a; + wire hdo_b; + wire [3:0] hdo_a,hdo_c,hdo_e; + wire [7:0] hdo_d; + wire [1:0] hdl_b,hdl_d,hdl_f,hdl_g,hdl_h; + wire [2:0] hdl_a,hdl_c,hdl_e; + wire [5:0] hdr_a,hdr_b,hdr_c,hdr_d,hdr_e,hdr_f,hdr_g,hdr_m; + + wire [66:0] state_0,state_group_50,state_group_60; // for the Gruppe 2 opcodes + + // Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2 + + parameter addr_nop = 19'b10_0000_0000_0_0000_0000; // all parameter to 0 + parameter push_op = 19'b10_0111_0000_1_1010_0000; // i.e. for BSR, ENTER ... + parameter push_ea = 19'b10_0111_0000_1_1010_0011; // SAVE middle + parameter pop_op = 19'b10_1011_0010_1_0000_1000; // RET/RESTORE + parameter adddisp = 19'b10_0010_0000_0_0000_0011; // for RET : reuse of EA + parameter adddispn = 19'b10_0010_0000_0_0000_0000; // for RETT : add Disp to Stack + parameter save_sp = 19'b10_0000_0000_1_0000_0000; // u.a. RET : update of Stack + parameter next_po = 19'b10_1011_0010_1_0000_1011; // RESTORE middle + parameter dispmin = 19'b10_0010_0000_0_0100_0011; // Reuse for ENTER + parameter rmod_rxp = 19'b10_1001_0000_1_0000_0100; // MODUL+0 read : SB , SP Update , therefore no LDEA + parameter rmod_rtt = 19'b10_1001_0000_0_0000_0100; // MODUL+0 read : SB , no LDEA + parameter rmod_4 = 19'b10_1011_0000_0_0001_0100; // MODUL+4 read : Link Table Base + parameter rmod_8 = 19'b10_1011_0000_0_0010_0100; // MODUL+8 read : Program Base + parameter rdltab = 19'b10_1010_0000_0_1000_0000; // Link table read - EA Phase + parameter ea_push = 19'b10_0110_0000_0_1010_0011; // CXP : 2. Push EA Phase + parameter ea_min8 = 19'b10_1010_0000_0_1011_0011; // CXP : reuse of MOD+8 + parameter pop_ru = 19'b10_1010_0010_0_0000_1011; // RXP : EA Phase MOD POP + parameter rd_icu = 19'b00_1001_0000_0_1100_0010; // Read ICU : Byte of fix address + parameter get_vec = 19'b10_1001_0000_0_01xx_0000; // Read Exception-Vector : Index Exception No. + parameter get_veci = 19'b10_1001_0110_0_0000_0000; // Read Exception-Vector : Index external Interrupt + parameter load_ea = 19'b10_0010_0000_0_0000_0000; // used for store of TEAR and MSR + parameter save_msr = 19'b10_0010_0001_0_0000_0000; // used for store of TEAR and MSR + parameter ivar_adr = 19'b10_0000_0100_0_0000_0010; // only pass SRC1 + parameter st_trans = 19'b00_1001_0100_0_0000_0000; // Translate at String : SRC1 + SRC2 , Byte + parameter src_x = 7'hxx; + parameter dest_x = 6'hxx; + parameter imme = {1'b1,6'hxx}; + parameter frame = 7'h18; + parameter ibase = 7'h1E; + parameter modul = 7'h1F; + parameter w_msr = 6'h0A; + parameter w_tear = 6'h0B; + parameter fsr_r = 6'h17; // not defined register for FSR for opcodes LFSR and SFSR + parameter temp_l = 6'h3C; + parameter temp_h = 6'h3D; // second last space for 8B TEMP register + parameter temp_1 = 6'h3E; // Backup for register at String operations + parameter temp_2 = 6'h3F; + parameter rtmpl = 7'h3C; + parameter rtmph = 7'h3D; + parameter rtmp1 = 7'h3E; + parameter rtmp2 = 7'h3F; + parameter op_mov = 11'h345; + parameter op_adr = 11'h349; + parameter op_add = 11'h340; // for CXP + parameter op_flip = 11'h364; // for CXP : LSHD -16,Ri + parameter op_lmr = 11'h36A; // for LPR CFG, LMR and CINV + parameter op_wrp = 11'h387; // for CXP : write PSR , used also for Exception processing + parameter op_ldp = 11'h388; // for RETT and RETI : load of PSR from Stack + parameter op_zex = 11'h076; // Zero Extension for ICU Vector - is also used at String Option "T" + parameter op_cop = 8'hDD; // Coprozessor Opcode + + // ++++++++++++++++++++++++++ The switch logic for the state machine +++++++++++++++++++++++++++++ + + always @(ANZ_VAL) + case (ANZ_VAL) + 3'd0 : valid = 3'b000; + 3'd1 : valid = 3'b001; + 3'd2 : valid = 3'b011; + default : valid = 3'b111; + endcase + + assign next = ( PHASE_0 ? op_ok : // Opcode decoded or Exception processed + // Displacement or Immediate operand and external memory access can happen in parallel + // i.e. addressing mode Memory Relative + ( ((~dim_feld[0] | ACC_DONE) & (~dim_feld[3] | di_stat[0])) // ACC_DONE resets dim_feld + // long operation + & ~(long_reg & ~DONE) ) ) + // hard break : abort or fpu_trap or dvz_trap or ovf_flag + | abbruch ; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) long_reg <= 1'b0; + else + long_reg <= next ? do_long : long_reg; // START[1] + + always @(posedge BCLK or negedge BRESET) // the central phase register + if (!BRESET) phase_reg <= 8'h0; + else + if (next) phase_reg <= new_op[47:40]; + + always @(*) // next switch of micro program counter + casex ({PHASE_0,op_ok,dim_feld[3],di_stat[0]}) + 4'b11_xx : USED = {1'b0,~op_1byte,(op_1byte | op_3byte)}; + 4'b0x_11 : USED = di_stat[3:1]; + default : USED = 3'd0; + endcase + + // Special phases + + assign PHASE_0 = (phase_reg == 8'h00); // During Phase 0 the opcode is decoded + + assign NEXT_PCA = PHASE_0 & ~ovf_flag & ~dbg_flag; + + // Pulse to transfer from Trace Bit to Pending Trace Bit, only once in the beginning of phase 0 + // The priority is such that a TRACE exception is served before an UNDEFINED/ILLEGAL exception + always @(posedge BCLK) no_t2p <= PHASE_0 & ~op_ok; + assign t2p = PHASE_0 & ~no_t2p; // signal to I_PFAD + + // ++++++++++++++++++++++++++ global control signals ++++++++++++++++ + + assign de_flag = CFG[8]; + assign ivec_flag = CFG[0]; + assign dvz_trap = TRAPS[1]; + assign fpu_trap = TRAPS[0]; + + always @(posedge BCLK) nmi_reg <= {nmi_reg[0],NMI_N}; // one clock sync and than falling edge detection + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) nmi_flag <= 1'b0; + else nmi_flag <= (nmi_reg == 2'b10) | (nmi_flag & ~(phase_reg == 8'h82)); + + always @(posedge BCLK) int_flag <= PSR[11] & ~INT_N; // one clock to synchronise + + assign stop = (int_flag | nmi_flag) & PHASE_0 & ~stop_d; // neccesary if FPU_TRAP and INT at the same time + assign interrupt = (int_flag | nmi_flag) & (~PHASE_0 | stop_d); + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) stop_d <= 1'd0; + else stop_d <= stop; + + // ++++++++++++++++++++++++++ Exception processing +++++++++++++++ + + // IC_ABORT is valid if Opcode Decoder cannot continue + assign iabo_fall = IC_ABORT & (PHASE_0 ? ~op_ok : (~di_stat[0] & dim_feld[3])); + + always @(posedge BCLK) iabort <= iabo_fall & ~ia_save; // DC_ABORT ist a pulse + always @(posedge BCLK) ia_save <= iabo_fall; + + // mmu_sel is used in ADDR_UNIT + always @(posedge BCLK) mmu_sel <= DC_ABORT | (mmu_sel & ~iabort); // 1 = DCACHE , 0 = ICACHE + assign MMU_UPDATE[0] = mmu_sel; + + assign abort = DC_ABORT | iabort; + + // that is the end of String loops where interrupts are checked : 8'hC7 & 8'hCF + assign string_ende = (phase_reg[7:4] == 4'hC) & (phase_reg[2:0] == 3'b111); // attention : 8'hCF does not exist + + always @(posedge BCLK) if (PHASE_0 || string_ende) type_nmi <= nmi_flag; // during processing kept stable + + assign svc_flag = (OPREG[7:0] == 8'hE2) & valid[0]; // Vector 5 : 0101 , Illegal Vector 4 : 0100 + assign bpt_flag = (OPREG[7:0] == 8'hF2) & valid[0]; // Vector 8 : 1000 , Undefined Vec. 10 : 1010 + assign flag_flag = (phase_reg == 8'h89) & flag; // Vector 7 - has an own state + assign trac_flag = t2p & PSR[10]; // Vector 9 : 1001 , PSR[10] = P Bit , Pending Trace + assign ovf_flag = (ovf_pipe[3] & flag) | (ovf_pipe[1] & TRAPS[2]); // Vector 13 : 1101 + assign dbg_flag = dbg_trap | (dbg_s & PHASE_0); // Vector 14 : 1110 + + // abort + dvz_trap during a opcode, fpu_trap + ovf_flag + dbg_flag later + assign abbruch = abort | fpu_trap | dvz_trap | ovf_flag | dbg_flag; // this 5 stop everything + assign abbruch2 = abort | fpu_trap | dvz_trap | ovf_flag; // for exc_vector generation + + // forces the next step of state machine (op_ok), generates otype="11" for Trap Service + assign exception = interrupt | svc_flag | bpt_flag | ILL | UNDEF | trac_flag | abbruch; + + // a TRACE Exception is done before the opcode execution + assign misc_vectors = trac_flag ? 4'h9 : {(bpt_flag | UNDEF),(svc_flag | ILL),UNDEF,svc_flag}; // the vectors are exclusiv + + always @(posedge BCLK) + if (PHASE_0 || abbruch) // ABORTs, fpu_trap, dvz_trap + ovf_flag can happen every time + begin + exc_vector <= abbruch ? (abbruch2 ? {ovf_flag,(dvz_trap | ovf_flag),~ovf_flag,(fpu_trap | ovf_flag)} : 4'hE) + : (interrupt ? {3'b0,nmi_flag} : misc_vectors); // misc_vectors is default + end + else + if (flag_flag) exc_vector <= 4'h7; // FLAG-Trap + else + if (interrupt && string_ende) exc_vector <= {3'b0,nmi_flag}; + + assign psr_code[2] = ~psr_code[1]; // Absicht : codiert das Sichern des PSR bei Exception-Entry + assign psr_code[1] = abort | ILL | UNDEF | trac_flag; // enable for reseting the P-Bit during write of PSR to stack + assign psr_code[0] = (interrupt & ~fpu_trap) | abort; // enable for reseting the I-Bit of new PSR + + // valid codes are x'89 to x'8F + assign op_psr = {8'b0_00_1000_1,psr_code}; // is used during first clock cylce after exception, is transfered as OPCODE to I_PFAD + + // Specialitiies : ABORT stores address & flags , the Interrrupts read vectors : all is used in big CASE + assign abo_int = (exc_vector == 4'h2) | (exc_vector[3:1] == 3'b000); + assign ai_next = (exc_vector == 4'h2) ? {load_ea,8'h84,4'h0} : {rd_icu,8'h82,4'h1}; + + assign save_pc = {7'b10_0010_0,dia_flag,7'b00_0_0000,dia_flag,3'b001}; // Exception : PC_ARCHI => EA, special case DIA + assign no_trap = ~fpu_trap & ~ovf_flag & ~dbg_flag; // suppresion of WREN and LD_OUT[1] and ADDR_UNIT operation + + // ++++++++++++++++++++++++++ Overflow Trap ++++++++++++++ + + always @(posedge BCLK) + if (ovf_flag || !PSR[4]) ovf_pipe <= 4'd0; + else + if (PHASE_0) ovf_pipe <= {ovf_pipe[2],(ovf_op & op_ok),ovf_pipe[0],(ovf2_op & op_ok)}; // V-Bit switches on + + assign ovf_op = ( ((OPREG[6:2] == 5'b000_11) // ADDQi + | (OPREG[3:2] == 2'b00)) & (OPREG[1:0] != 2'b10)) // ADDi,ADDCi,SUBi,SUBCi + | ((OPREG[7:0] == 8'h4E) & OPREG[13] & (OPREG[11:10] == 2'b00)) // NEGi,ABSi + | ((OPREG[7:0] == 8'hEE) & ~OPREG[10]); // CHECKi + + assign ovf2_op = ((OPREG[6:2] == 5'b100_11) & (OPREG[1:0] != 2'b10)) // ACBi, these overflows have no FLAG + | ((OPREG[13:10] == 4'h1) & (OPREG[7:0] == 8'h4E)) // ASHi + | ( OPREG[13] & (OPREG[11] == OPREG[10]) & (OPREG[7:0] == 8'hCE)); // MULi,DEIi,QUOi,DIVi + + // ++++++++++++++++++++++++++ Debug Trap ++++++++++++++ + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) dbg_s <= 1'b0; + else dbg_s <= dbg_trap | (dbg_s & ~((exc_vector == 4'hE) & (phase_reg == 8'h81))); + + always @(posedge BCLK) dbg_en <= op_ok | ~PHASE_0; + + assign pc_match = dbg_en & TRAPS[3] & PHASE_0 & ~exception; // TRAPS[3] is only combinatorical + + always @(posedge BCLK) dbg_trap <= (pc_match | (addr_cmp & PHASE_0)) & TRAPS[5]; // TRAPS[5] = Enable Trap + + always @(posedge BCLK) addr_cmp <= TRAPS[4] | (addr_cmp & ~PHASE_0); // TRAPS[4] = CAR HIT + + // ++++++++++++++++++++++++++ Special case String Abort ++++++++++++++ + + // Flags cleared if entry and exit of string operation and during Abort sequence, not valid for MOVM/CMPM + // special case UNTIL/WHILE : reset if exit (op_feld_reg[17] = 1 = UNTIL) + assign clr_sflag = (phase_reg == 8'hC0) | (phase_reg == 8'hC7) | (phase_reg == 8'hC8) | (phase_reg == 8'h81) + | (((phase_reg == 8'hD7) | (phase_reg == 8'hDF)) & ~(STRING[3] ^ op_feld_reg[17])) ; + assign set_src = (phase_reg == 8'hC1) | (phase_reg == 8'hC9); + assign set_dest = (phase_reg == 8'hC4) | (phase_reg == 8'hCC); + + always @(posedge BCLK or negedge BRESET) // R1 is modified + if (!BRESET) ssrc_flag <= 1'b0; + else ssrc_flag <= (set_src & ~kurz_st) | (ssrc_flag & ~clr_sflag); + + always @(posedge BCLK or negedge BRESET) // R2 is modified + if (!BRESET) sdest_flag <= 1'b0; + else sdest_flag <= (set_dest & ~kurz_st) | (sdest_flag & ~clr_sflag); + + assign rrepa = {7'b1000_011,~sdest_flag}; // R1 and if necessary R2 restore + + // ++++++++++++++++++++++++++ The one byte opcodes +++++++++++++++++++ + + // The one byte opcodes have a special case : one byte opcode but the second byte should be valid too + // Used with SAVE, RESTORE, ENTER and EXIT with their reg list. + // The advantage is that the reg list is store in op_feld_reg. + + // [52:34] addressing + // [33:20] register + // [19:18] 1 or 2 Byte opcode + // [17:16] BSR/BR + // [15:8] next phase + // [7:4] START + LD_OUT + // [3:0] operand access : Displacement or Speicher + + always @(*) // SVC (E2) and BPT (F2) decode as exception + casex (OPREG[7:0]) + 8'hxA : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b01,8'h01,4'h0,4'hE}; // Bcc , DISP read + 8'h02 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b10,8'h01,4'h0,4'hE}; // BSR , DISP read + 8'h12 : op1_feld = {pop_op , src_x, stack, 2'b01,2'b00,8'h2A,4'h0,4'h1}; // RET , DISP later + 8'h22 : op1_feld = {rmod_4 , src_x, modul, 2'b01,2'b00,8'h35,4'h0,4'h1}; // CXP + 8'h32 : op1_feld = {pop_op, src_x, stack, 2'b01,2'b00,8'h40,4'h0,4'h1}; // RXP + 8'h42 : op1_feld = {pop_op, src_x, stack, 2'b01,2'b00,8'h46,4'h0,4'h1}; // RETT + 8'h52 : op1_feld = {rd_icu, src_x, src_x, 2'b01,2'b00,8'h45,4'h0,4'h1}; // RETI + 8'h62 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h30,4'h0,4'h0}; // SAVE + 8'h72 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h32,4'h0,4'h0}; // RESTORE + 8'h82 : op1_feld = {push_op , frame, stack, 2'b10,2'b00,8'h2D,4'h2,4'h1}; // ENTER : PUSH FP + 8'h92 : op1_feld = {addr_nop, src_x, src_x, 2'b10,2'b00,8'h32,4'h0,4'h0}; // EXIT : POP FP + 8'hA2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h00,4'h0,4'h0}; // NOP + 8'hB2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h88,4'h0,4'h0}; // WAIT + 8'hC2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h88,4'h0,4'h0}; // DIA + 8'hD2 : op1_feld = {addr_nop, src_x, src_x, 2'b01,2'b00,8'h89,4'h0,4'h0}; // FLAG + default : op1_feld = {19'hxxxxx,14'hxxxx, 2'b00,2'b00,16'hxxxx}; + endcase + + assign op_1byte = op1_feld[18] & valid[0]; + assign op_12byte = op1_feld[19] & (valid[1:0] == 2'b11); + + assign new_addr = op1_feld[52:34]; + assign new_regs = op1_feld[33:20]; + assign new_ph = op1_feld[15:8]; + assign new_nx = op1_feld[7:0]; // at Bcond DISP read + + assign pop_fp = new_fp ? pop_op : addr_nop; + assign ppfp = new_fp ? 8'h34 : 8'h00; + + always @(posedge BCLK) + if (PHASE_0) + begin + ex_br_op <= op1_feld[17:16]; // BSR/BR + cc_feld <= OPREG[7:4]; + new_fp <= (OPREG[7:6] == 2'b10); // not decoded complete but is sufficient + reti_flag <= OPREG[4]; // only difference between RETI and RETT is important + dia_op <= OPREG[6]; // only difference between DIA and WAIT is important + end + + always @(posedge BCLK) dia_flag <= dia_op & (phase_reg == 8'h88); // special case DIA compared to WAIT : Addr DIA to Stack + + always @(posedge BCLK) // Format 1 opcodes write always DWord to reg, the same is true for Exceptions + if (PHASE_0 || abbruch) format1 <= (valid[0] & (OPREG[3:0] == 4'h2)) | exception; + else + if (flag_flag || (interrupt && string_ende)) format1 <= 1'b1; + + // Branch etc. CXP CXPD + assign store_pc = (phase_reg == 8'd1) | (phase_reg == 8'h37) | (phase_reg == 8'h6B); // only save in DIN Reg of DATENPFAD + assign jump = (ex_br_op[0] & branch) | (acb_reg & ~ACB_ZERO) | ex_br_op[1]; + + always @(posedge BCLK) ldpc_phase <= (phase_reg == 8'h3E) // PC load at CXP/Traps , all one clock cycle guaranted + | (phase_reg == 8'h43) // PC load at RXP + | ((phase_reg == 8'h49) & reti_flag) // PC load at RETI + | (phase_reg == 8'h4E) // PC load at RETT + | (phase_reg == 8'h66) // PC load at JUMP/JSR/CASE + | (phase_reg == 8'h7B); // PC load at DE = Direct Exception + + assign NEW = ((phase_reg == 8'd1) & jump & di_stat[0]) | LOAD_PC; + assign LOAD_PC = ((phase_reg == 8'h2B) & di_stat[0]) // only one pulse, but DISP must be ok => di_stat[0] (RET) + | ldpc_phase; + + assign no_modul = de_flag ? {1'b0,dest_x} : {1'b1,modul[5:0]}; + + assign negativ = PSR[7]; + assign zero = PSR[6]; + assign flag = PSR[5]; + assign larger = PSR[2]; + assign carry_psr = PSR[0]; + + assign rett_exc = ~reti_flag & (phase_reg == 8'h4B); // special case RETT : Stack can change during opcode + always @(posedge BCLK) phase_exc <= (phase_reg == 8'h80); // 1. Exception phase + always @(negedge BCLK) if (PHASE_0 || phase_exc || rett_exc) s_user <= PSR[9]; // Select Bit for Stack, delayed update + always @(negedge BCLK) + if (PHASE_0 || phase_exc) s_mod <= {PSR[9],~PSR[9]}; + else + if (rett_exc) s_mod <= s_mod | {PSR[9],~PSR[9]}; // Both can be updated + + always @(cc_feld or zero or carry_psr or larger or negativ or flag) + case (cc_feld) + 4'h0 : branch = zero; // EQual + 4'h1 : branch = ~zero; // Not Equal + 4'h2 : branch = carry_psr; // Carry Set + 4'h3 : branch = ~carry_psr; // Carry Clear + 4'h4 : branch = larger; // Higher + 4'h5 : branch = ~larger; // Lower or Same + 4'h6 : branch = negativ; // Greater Than + 4'h7 : branch = ~negativ; // Less or Equal + 4'h8 : branch = flag; // Flag Set + 4'h9 : branch = ~flag; // Flag Clear + 4'hA : branch = ~larger & ~zero; // LOwer + 4'hB : branch = larger | zero; // Higher or Same + 4'hC : branch = ~negativ & ~zero; // Less Than + 4'hD : branch = negativ | zero; // Greater or Equal + 4'hE : branch = 1'b1; // True + 4'hF : branch = 1'b0; // False + endcase + + // +++++++++++++++++++++++ Register List Processing ++++++++++++++++++++++++++++ + + always @(posedge BCLK) init_rlist <= PHASE_0 | (phase_reg == 8'h2E); + + always @(posedge BCLK) + if (PHASE_0) rpointer <= 3'b000; + else + if (ACC_DONE || init_rlist) rpointer <= reg_nr; + + REG_LIST scanner ( .DIN(op_feld_reg[22:15]), .INIT(init_rlist), .IPOS(rpointer), .VALID(save_reg), .OPOS(reg_nr) ); + + assign saver = {4'h0,reg_nr}; + + always @(posedge BCLK) if (ACC_DONE || init_rlist) resto <= {3'h0,~reg_nr}; // EXIT and RESTORE have the list mirrored : R0...R7 + + // ++++++++++++++++++++++++++ Processing of Displacement and Immediate Operand +++++++++++++++++++ + + always @(posedge BCLK or negedge BRESET) // Flag for DISP and IMME access + if (!BRESET) dim_feld[3] <= 1'b0; + else dim_feld[3] <= next ? new_op[3] : ~di_stat[0] & dim_feld[3]; + + always @(posedge BCLK) if (next) dim_feld[2:1] <= new_op[2:1]; + + always @(posedge BCLK or negedge BRESET) // Flag for external access + if (!BRESET) dim_feld[0] <= 1'b0; + else dim_feld[0] <= next ? new_op[0] : ~ACC_DONE & dim_feld[0]; + + // special case QWORD, last term for security + always @(posedge BCLK) qw_flag <= dim_feld[0] & ACC_DONE & (ACC_FELD[13:12] == 2'b11) & ~qw_flag; + + assign LD_IMME = (dim_feld[3] & (dim_feld[2:1] != 2'b11)) | short_op | store_pc; // Data multiplexer + assign LD_DIN = (di_stat[0] & dim_feld[3] & (dim_feld[2:1] != 2'b11)) // Enable for DIN Register + | (ACC_DONE & dim_feld[0]) | qw_flag | short_op | store_pc; // next not possible : i.e. immediate and disp parallel + assign ld_disp = (dim_feld[3:1] == 3'b111); // Enable for DISP Register + + // Signal to ADDR_UNIT , only Displacement critical + assign disp_ok = ld_disp ? di_stat[0] : 1'b1; + + always @(dim_feld or OPREG or valid or ANZ_VAL) // Bit 0 is "Data ok", the upper 3 bits are for USED + casex ({dim_feld[2:1],OPREG[7:6]}) + 4'b00_xx : di_stat = {3'b001,valid[0]}; + 4'b01_xx : di_stat = {3'b010,(valid[1] & valid[0])}; + 4'b10_xx : di_stat = {3'b100,ANZ_VAL[2]}; + 4'b11_0x : di_stat = {3'b001,valid[0]}; + 4'b11_10 : di_stat = {3'b010,(valid[1] & valid[0])}; + 4'b11_11 : di_stat = {3'b100,ANZ_VAL[2]}; + endcase + + always @(OPREG) + casex (OPREG[7:6]) + 2'b0x : disp_val = {{26{OPREG[6]}},OPREG[5:0]}; + 2'b10 : disp_val = {{19{OPREG[5]}},OPREG[4:0],OPREG[15:8]}; + 2'b11 : disp_val = {{3{OPREG[5]}},OPREG[4:0],OPREG[15:8],OPREG[23:16],OPREG[31:24]}; + endcase + + assign DISP_BR = disp_val; // DISP is also used for Bcc opcode + + // The generator for DISP : data is used in ADDR_UNIT + always @(*) + casex ({ld_disp,disp_sel}) // disp_sel from new_op + 5'b1_00xx : DISP = disp_val; + 5'b1_01xx : DISP = 32'h0 - disp_val; // special case for ENTER + 5'b1_1xxx : DISP = {disp_val[29:0],2'b00}; // DISP*4 for External Address Mode + 5'b0_11xx : DISP = {20'hFFFFF,3'h7,type_nmi,8'h00}; // Interrupt Service Address + 5'b0_1000 : DISP = 32'hFFFF_FFFF; // PUSH Byte + 5'b0_1001 : DISP = 32'hFFFF_FFFE; // PUSH Word + 5'b0_1010 : DISP = 32'hFFFF_FFFC; // PUSH DWord + 5'b0_1011 : DISP = 32'hFFFF_FFF8; // PUSH QWord + 5'b0_01xx : DISP = {26'h0,exc_vector,2'b00}; // the exception vector as Offset for INTBASE + 5'b0_00xx : DISP = {28'h0,disp_sel[1:0],2'b00}; // 0,+4,+8,+12 used with MOD, default is 0 + endcase + + always @(short_op or dim_feld or OPREG or op_setcfg or setcfg_lsb) + casex ({short_op,dim_feld[2:1]}) + 3'b000 : imme_i = op_setcfg ? {28'h0000_00F,OPREG[2:0],setcfg_lsb} : {24'hxx_xxxx,OPREG[7:0]}; + 3'b001 : imme_i = {16'hxxxx,OPREG[7:0],OPREG[15:8]}; + 3'b01x : imme_i = {OPREG[7:0],OPREG[15:8],OPREG[23:16],OPREG[31:24]}; + 3'b1xx : imme_i = {{29{OPREG[10]}},OPREG[9:7]}; // for MOVQ etc. only OPREG can be used + endcase + + assign IMME_Q = store_pc ? PC_SAVE : imme_i; + + // ++++++++++++++ Stack Control +++++++++++++++++ + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) new_spsel <= 1'b0; + else new_spsel <= spupd | (new_spsel & ~PHASE_0 & ~fpu_trap & ~dvz_trap); + + always @(posedge BCLK) upd_info <= PHASE_0 & new_spsel; // one clock cycle earlier a change occurs, i.e. ADDF TOS,F0 => fpu_trap + + assign do_xor = fpu_trap ? upd_info : (PHASE_0 & new_spsel); + + always @(negedge BCLK or negedge BRESET) + if (!BRESET) stack_sel <= 2'b00; + else + if (do_xor) stack_sel <= stack_sel ^ s_mod; + + // Special case RETT + always @(posedge BCLK) if (!phase_reg[1]) old_su <= s_user; // is tested in state x'49 and used in x'4B + assign ttstak = {1'b0,((old_su == PSR[9]) ^ stack_sel[PSR[9]]),3'b110,PSR[9],1'b1}; + + // ++++++++++++++ 2 byte opcodes +++++++++++++++++ + + // Hint : short_op is decoded separatly + + // [47:45] Source : [2] TOS=>(SP), [1] Ri => (Ri), [0] 1=access of memory + // [44:42] Destination : like [47:45] + // [41] long opcode [41:39] only for standard sequenz - not Gruppe 2 + // [40] src2_flag - Source 2 is read + // [39] dest_flag - a target operand exists + // [38:33] src1_r Register field, no message about Immediate + // [32:27] src2_r Register field + // [26:25] src1_le Length of Source1 - this is used for qword + // [24:23] src2_le Length of Source2 : 00=1/01=2/10=4/11=8 Bytes => WMASKE + // [22:18] src1 field + // [17:13] src2 field + // [12:11] op_type 2 Bit for sort of opcode + // [10] FL : F=1/L=0 + // [9:8] original BWD : B=00/W=01/D=11 + // [7:0] opcode: operation code + + assign valid_size = (OPREG[1:0] != 2'b10) & (valid[1:0] == 2'b11); // valid size + valid OPREG-Bytes + + assign hzl_a = (OPREG[1:0] == 2'b11) ? 2'b10 : OPREG[1:0]; // length field recoded + assign hzl_b = {1'b0,OPREG[1:0]}; // standard Length field + assign hzr_a = {3'b000,OPREG[13:11]}; // SRC2 or SRC1 regfield + assign hzr_b = {3'b000,OPREG[8:6]}; // SRC2 regfield + assign hzr_s = {((OPREG[15:11] == 5'h17) ^ stack_sel[s_user]),3'b110,s_user,1'b1}; // USER or SUPERVISOR Stack, TOS special case + // Special case LPR & SPR regfield: + always @(OPREG or stack_sel or s_user) + casex ({OPREG[10:7]}) + 4'b1001 : hzr_c = {stack_sel[s_user],3'b110,s_user,1'b1}; // USER or SUPERVISOR Stack + 4'b1011 : hzr_c = {stack_sel[1] ,3'b110,1'b1, 1'b1}; // USER Stack + 4'b1100 : hzr_c = OPREG[6] ? temp_h : 6'h1C; // CFG special case : LPR : SPR + default : hzr_c = {2'b01,OPREG[10:7]}; + endcase + + // Unfortunately SETCFG must be implemented : it is transformed to a two byte opcode with one byte IMM operand + assign setcfg = (OPREG[13:0] == 14'h0B0E) & (valid[1:0] == 2'b11); + + always @(*) + casex ({setcfg,OPREG[10:2]}) + // Short-Op Codes , ACB is an ADD with following jump + 10'b0xxxx_x0011 : op2_feld = {6'o11,3'o3,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'h40}; // ADDQ ACB + 10'b0xxxx_00111 : op2_feld = {6'o11,3'o2,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'h41}; // CMPQ + 10'b0xxxx_01011 : op2_feld = {6'o11,3'o1,hzr_c,hzr_a,hzl_a,hzl_a,5'h00,OPREG[15:11],2'b00,hzl_b,8'h45}; // SPR + // Scond is moving the SHORT operand in the Integer area as condition field + 10'b0xxxx_01111 : op2_feld = {6'o11,3'o1,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'h7A}; // Format 7, A=(UNDEF) + 10'b0xxxx_10111 : op2_feld = {6'o11,3'o1,6'hxx,hzr_a,hzl_a,hzl_a,5'h14,OPREG[15:11],2'b00,hzl_b,8'h45}; // MOVQ + 10'b0xxxx_11011 : op2_feld = {6'o11,3'o1,hzr_a,hzr_c,hzl_a,2'b10,OPREG[15:11],5'h00,2'b00,hzl_b,8'h76}; // LPR => MOVZiD + // Format 3 opcodes : + 10'b00x10_11111 : op2_feld = {6'o11,3'o1,hzr_a,6'h1D,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b00,hzl_b,4'h3,OPREG[10:7]}; // BIC/SPSR + 10'b0x100_11111 : op2_feld = {6'o61,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'h3,OPREG[10:7]}; // JUMP/JSR + 10'b01110_11111 : op2_feld = {6'o11,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'h3,OPREG[10:7]}; // CASE + // Format 4 opcodes : main group + 10'b0xxxx_xxxx0 : op2_feld = {6'o11,3'o3,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OPREG[5:2]}; + 10'b0xxxx_x0001 : op2_feld = {6'o11,3'o2,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OPREG[5:2]}; //CMP no WR + 10'b0xxxx_x0101 : op2_feld = {6'o11,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,4'h4,OPREG[5:2]}; //MOV no 2.Op + 10'b0xxxx_x1101 : op2_feld = (OPREG[10:9] == 2'b00) ? // target is Register => standard flow + {6'o11,3'o2,hzr_a,hzr_b,hzl_a,2'bxx,OPREG[15:6], 2'b00,hzl_b,4'h4,OPREG[5:2]} // TBIT + : {6'o14,3'o2,hzr_a,hzr_b,hzl_a,2'b00,OPREG[15:6], 2'b10,hzl_b,4'h4,OPREG[5:2]}; + // ADJSPi + 10'b01010_11111 : op2_feld = {6'o11,3'o3,hzr_a,hzr_s,hzl_a,2'b10,OPREG[15:11],5'h00,2'b00,hzl_b,8'h48}; // is a SUBD + // ADDR, length field not valid + 10'b0xxxx_x1001 : op2_feld = {6'o61,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:6], 2'b00,hzl_b,8'h49}; + 10'b00000_11111 : op2_feld = {6'o71,3'o1,hzr_a,hzr_b,hzl_a,hzl_a,OPREG[15:11],5'h00,2'b10,hzl_b,4'h3,OPREG[10:7]}; // CXPD no Opcode + // SETCFG => MOV Befehl , SRC1 is genrated for 32 bit , target is Register temp_h + 10'b1xxxx_xxxxx : op2_feld = {40'b001001_001_000000_111101_00_10_10100_00000_00_011, 8'h76}; + default : op2_feld = {40'hxx_xxxx_xxxx,4'hA,4'hx}; + endcase + + assign op_2byte = (valid_size | setcfg) & ~op2_feld[7]; // it must be for sure shown "Invalid Opcode" + + // Special case : the quick opcodes with the exception SPR and LPR + assign short_op = ((~OPREG[5]) | (OPREG[6:4] == 3'b011)) & (OPREG[3:2] == 2'b11) & valid_size & PHASE_0; + always @(posedge BCLK) if (PHASE_0) short_op_reg <= short_op; + assign short_def = PHASE_0 ? short_op : short_op_reg; // for the big state machine + assign op_sho = (OPREG[6:4] == 3'b011) ? 11'h07A : op_mov; // Special case Scond at Index as Dest. , used only in Phase 0 + + // 2. special case ACB + assign acb_op = (OPREG[6:2] == 5'h13) & valid_size; + always @(posedge BCLK) if (PHASE_0) acb_reg <= acb_op; + assign acb_flag = PHASE_0 ? acb_op : acb_reg; + assign goacb = acb_flag ? 8'h28 : 8'h00; // x'28 = 40 , wait jump at REG operation - short-op special case + + // 3. special case load of PSR and Init-Done opcodes : because of U bit in PSR a restart must follow, + // CINV and LMR PTB must wait until Init-Done and than Restart. + // All variants of LPR and BIC/S have an extra cycle due to TRACE operation + always @(OPREG) + casex (OPREG[18:0]) + 19'bxxx_xxxxx_1101_110_11_xx : waitop = 9'h14C; // LPRi PSR,... + 19'bxxx_xxxxx_1100_110_11_xx : waitop = 9'h174; // LPRi CFG,... + 19'bxxx_xxxxx_0x10_111_11_xx : waitop = 9'h14C; // BICPSRi/BISPSRi ... + 19'bxxxx_x_0010_xx_0000_1110 : waitop = 9'h174; // SETCFG [] + 19'bxxxx_0_0010_xx_0001_1110 : waitop = 9'h174; // LMR - at the end Restart + 19'bxxxx_0_1001_xx_0001_1110 : waitop = 9'h174; // CINV - at the end Restart + default : waitop = 9'h000; + endcase + + assign dowait = waitop[7:0]; // is used in Phase 0 if PSR is loaded from Register + always @(posedge BCLK) if (PHASE_0) wait_reg <= waitop; + + // Here 2. and 3. special case are coming together: + // Phase definition, end over jump for ACB , not used in Phase 0 + assign endea = acb_reg ? 8'h01 : (wait_reg[8] ? wait_reg[7:0] : 8'h00); + assign diacb = acb_reg ? 4'hE : 4'h0; // load Disp ? + + // special case ADJSPi : SP=SRC2 always 32 Bit + always @(posedge BCLK) + if (PHASE_0) dw_info <= (OPREG[10:2] == 9'b1010_11111); + else dw_info <= dw_info & ~phase_reg[7]; // for security at ABORT + + // SETCFG : Flag to transform the Byte Immeadiate operand + always @(posedge BCLK) if (PHASE_0) op_setcfg <= setcfg; + always @(posedge BCLK) if (PHASE_0) setcfg_lsb <= OPREG[15]; + + always @(posedge BCLK) if (PHASE_0) jsr_flag <= (OPREG[10:2] == 9'b1100_11111); // JSR : for PUSH + always @(posedge BCLK) // Bit opcodes to Register and EXT:SRC1 / INS:SRC2 + if (PHASE_0) bit_reg <= ((OPREG[3] ? ((OPREG[7:6] == 2'd0) ? OPREG[23:22] : OPREG[18:17]) : OPREG[10:9]) == 2'b00); + always @(posedge BCLK) if (PHASE_0) exin_cmd <= (~OPREG[10] & (OPREG[6:0] == 7'h2E)) & (valid[2:0] == 3'b111); + always @(posedge BCLK) if (PHASE_0) extract <= ~OPREG[7]; + always @(posedge BCLK) if (PHASE_0) inss_op <= (OPREG[13:10] == 4'h2) & (OPREG[7:0] == 8'hCE) & (valid[2:0] == 3'b111); // INSS + + // ++++++++++++++ 3 byte opcodes +++++++++++++++++ + + // [47:45] Source : [2] TOS=>(SP), [1] Ri => (Ri), [0] 1=access of memory + // [44:42] Destination : like [47:45] + // [41] long opcode [41:39] only for standard sequenz - not Gruppe 2 + // [40] src2_flag - Source 2 is read + // [39] dest_flag - a target operand exists + // [38:33] src1_r Register field, no message about Immediate + // [32:27] src2_r Register field + // [26:25] src1_le Length of Source1 - this is used for qword + // [24:23] src2_le Length of Source2 : 00=1/01=2/10=4/11=8 Bytes => WMASKE + // [22:18] src1 field + // [17:13] src2 field + // [12:11] op_type 2 Bit for sort of opcode + // [10] FL : F=1/L=0 + // [9:8] original BWD : B=00/W=01/D=11 + // [7:0] opcode: operation code + + assign hdx_a = OPREG[7] ? OPREG[8] : OPREG[10]; + assign hdo_a = OPREG[13:10]; + assign hdo_b = ~hdx_a; // long operation if L + assign hdo_c = {1'b0,OPREG[10],OPREG[7:6]}; // Format 8 opcodes + assign hdo_d = {6'b0101_00,OPREG[10],1'b0}; // CMPM/S or MOVM/S : 8'h52 or 8'h50 + assign hdo_e = {3'b011,OPREG[10]}; // Special codes for LOGB and SCALB due to DP_OUT datapath + // Definitions of length + assign hdl_a = {1'b0,OPREG[9:8]}; // i size, is used in OPER + assign hdl_b = (OPREG[9:8] == 2'b11) ? 2'b10 : OPREG[9:8]; // recode length field, is used in ACC field + assign hdl_c = OPREG[10:8]; // FL + BWD + assign hdl_d = {1'b1,~hdx_a}; // length FP + assign hdl_e = {OPREG[8],2'bxx}; // BWD don't care + assign hdl_f = (OPREG[18:17] == 2'b00) ? OPREG[9:8] : {OPREG[8],~(OPREG[9] ^ OPREG[8])}; // exclusiv for DEI + assign hdl_g = {(OPREG[9:8] != 2'b00),(OPREG[9:8] == 2'b00)}; // exclusiv for EXT/EXTS base operand + assign hdl_h = {(OPREG[9:8] != 2'b00),(OPREG[9:8] != 2'b01)}; // exclusiv for CHECK bound operand + // Register definitions + assign hdr_a = {3'b000,OPREG[21:19]}; // SRC1 Integer Register + assign hdr_b = {3'b000,OPREG[16:14]}; // SRC2 Integer Register + assign hdr_c = hdx_a ? {2'b10,OPREG[21:20],1'b0,OPREG[19]} : {2'b10,OPREG[21:19],1'b1}; + assign hdr_d = hdx_a ? {2'b10,OPREG[16:15],1'b0,OPREG[14]} : {2'b10,OPREG[16:14],1'b1}; + assign hdr_e = OPREG[11] ? {2'b10,OPREG[21:20],1'b0,OPREG[19]} : {2'b10,OPREG[21:19],1'b1}; + assign hdr_f = OPREG[11] ? {2'b10,OPREG[16:14],1'b1} : {2'b10,OPREG[16:15],1'b0,OPREG[14]}; + assign hdr_g = {3'b000,OPREG[16:15],~OPREG[14]}; // exclusiv for DEI/MEI + assign hdr_m = {3'b001,OPREG[17:15]}; // MMU Register Index 8-15 + + always @(*) + casex (OPREG[13:3]) + 11'b1000_xx_1100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h7,hdo_a}; // MULi + 11'b000x_xx_0100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, 2'b00,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a}; // ROTi,ASHi + 11'b0101_xx_0100x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, 2'b00,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a}; // LSHi + 11'b1x0x_xx_0100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a}; // NEGi,NOTi,ABSi,COMi + 11'b010x_xx_1100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,2'b01,OPREG[23:14],2'b00,hdl_a,4'h7,hdo_a}; // MOVX/ZiW + 11'b011x_xx_1100x : op3_feld = {6'o11,3'o1,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h7,hdo_a}; // MOVX/ZiD + 11'b0001_xx_0110x : op3_feld = {6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b00,hdl_a,4'h8,hdo_c}; // FFSi + // Floating Point opcodes + 11'b000x_xx_0011x : op3_feld = {6'o11,hdo_b,2'b01,hdr_a,hdr_d, hdl_b,hdl_d,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVif + 11'b010x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b11,2'b10,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVLF + 11'b011x_xx_0011x : op3_feld = {6'o11, 3'o5,hdr_e,hdr_f, 2'b10,2'b11,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // MOVFL + 11'b10xx_xx_0011x : op3_feld = {6'o11,hdo_b,2'b01,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // ROUNDi,TRUNCi + 11'b111x_xx_00111 : op3_feld = {6'o11,hdo_b,2'b01,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,4'h9,hdo_a}; // FLOORi + 11'b111x_xx_00110 : op3_feld = {6'o11, 3'o5,hdr_c,hdr_b, hdl_d,hdl_b,OPREG[23:14],2'b00,hdl_c,op_cop}; // SEARCH + 11'b0x00_0x_10111 : op3_feld = {6'o11,hdo_b,2'b11,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // ADDf,SUBf + 11'bxx00_0x_10110 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,op_cop}; // Coprocessor + 11'b1000_0x_10111 : op3_feld = {6'o11, 3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // DIVf + 11'b1100_0x_10111 : op3_feld = {6'o11,hdo_b,2'b11,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // MULf + 11'b0010_0x_1011x : op3_feld = {6'o11,hdo_b,2'b10,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // CMPf + 11'b0001_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // MOVf + 11'bx101_0x_10111 : op3_feld = {6'o11, 3'o1,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_a}; // NEGf,ABSf + 11'b001x_11_00111 : op3_feld = {6'o11,3'o1,hdr_a,fsr_r, 2'b10,2'b10,OPREG[23:19],5'b0,2'b00,3'o3,8'h92}; // LFSR + 11'b110x_11_00111 : op3_feld = {6'o11,3'o1,fsr_r,hdr_b, 2'b10,2'b10,5'b0,OPREG[18:14],2'b00,3'o3,8'h9C}; // SFSR + // MMU opcodes + 11'b0010_11_0001x : op3_feld = {6'o11,3'o1,hdr_a,temp_h,2'b10,2'b10,OPREG[23:19],5'b0,2'b00, 3'o3,8'h45}; // LMR + 11'b0011_11_0001x : op3_feld = {6'o11,3'o1,hdr_m,hdr_a, 2'b10,2'b10,5'b0,OPREG[23:19],2'b00, 3'o3,8'h45}; // SMR + // String opcodes + 11'b000x_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_c,hdo_d}; // MOVS,CMPS + 11'b0011_xx_0000x : op3_feld = {6'o11,3'o0,6'hxx,6'hxx, 2'bxx,2'b10,OPREG[23:14], 2'b10,hdl_c,hdo_d}; // SKPS + // Custom opcodes + 11'bxx01_0x_10110 : op3_feld = {6'o11, 3'o5,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,op_cop}; + // Integer Divisionen : QUOi REMi DIVi MODi and DEIi + MEIi + 11'b11xx_xx_1100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h7,hdo_a}; + 11'b10x1_xx_1100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_g, hdl_b,hdl_f,OPREG[23:14],2'b10,hdl_a,4'h7,hdo_a}; // DEI/MEI + // Gruppe 2 opcodes + 11'b0x11_xx_1010x : op3_feld = {6'o77,3'o1,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,8'h45}; // MOVUS,MOVSU + 11'b000x_xx_1100x : op3_feld = {6'o66,3'o0,hdr_a,hdr_b, 2'bxx,2'b10,OPREG[23:14],2'b10,hdl_c, hdo_d}; // MOVM/CMPM + 11'b001x_0x_1111x : op3_feld = {6'o11,3'o2,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'hC,hdo_a}; // DOTf,POLYf + 11'b0101_0x_1111x : op3_feld = {6'o11,3'o5,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b00,hdl_e,4'hB,hdo_e}; // LOGB + 11'b0100_0x_1111x : op3_feld = {6'o11,3'o7,hdr_c,hdr_d, hdl_d,hdl_d,OPREG[23:14],2'b10,hdl_e,4'hB,hdo_e}; // SCALB + 11'b0011_xx_1100x : op3_feld = {6'o50,3'o0,hdr_a,hdr_b, hdl_g,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h7,hdo_a}; // EXTS + 11'bxxx0_xx_1110x : op3_feld = {6'o71,3'o2,hdr_a,hdr_b, hdl_h,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h8,hdo_c}; // CHECK + 11'b0x1x_xx_0100x : op3_feld = (OPREG[18:17] == 2'b00) ? // target is register => standard flow + {6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a} // SBIT/CBIT + : {6'o14,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b10,hdl_a,4'h6,hdo_a}; + 11'b1110_xx_0100x : op3_feld = (OPREG[18:17] == 2'b00) ? // target is register => standard flow + {6'o11,3'o3,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a} // IBIT + : {6'o14,3'o3,hdr_a,hdr_b, hdl_b,2'b00,OPREG[23:14],2'b10,hdl_a,4'h6,hdo_a}; + 11'b1x11_xx_0100x : op3_feld = {6'o11,3'o7,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b00,hdl_a,4'h6,hdo_a}; // ADDP,SUBP + 11'bxxx0_xx_0010x : op3_feld = {6'o40,3'o0,hdr_a,hdr_b, hdl_g,hdl_b,OPREG[23:14],2'b10,hdl_c,4'h8,hdo_c}; // EXT + 11'bxxx0_xx_1010x : op3_feld = {6'o14,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h8,hdo_c}; // INS + 11'b0010_xx_1100x : op3_feld = {6'o14,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h8,hdo_a}; // INSS + 11'bxxx0_xx_0110x : op3_feld = {6'o61,3'o0,hdr_a,hdr_b, hdl_b,2'b10,OPREG[23:14],2'b10, 3'o3,4'h8,hdo_c}; // CVTP no Opcode + 11'bxxx1_xx_0010x : op3_feld = {6'o11,3'o2,hdr_a,hdr_b, hdl_b,hdl_b,OPREG[23:14],2'b10, 3'o3,8'h84}; // INDEX + // Gruppe 2 opcodes can have dedicated operation codes. Therefore the operation code definition here is "don't care" + 11'b000x_xx_0001x : op3_feld = {6'o70,3'o0,hdr_a,hdr_b, 2'b00,2'b10,OPREG[23:19],5'b0,2'b10,3'o0,8'h45}; // RDVAL+WRVAL + 11'b1001_11_0001x : op3_feld = {6'o11,3'o1,hdr_a,temp_h,2'b10,2'b10,OPREG[23:19],5'b0,2'b00,3'o3,8'h45}; // CINV + + default : op3_feld = {40'hxx_xxxx_xxxx,4'hA,4'hx}; + endcase + + assign op_3byte = (valid[2:0] == 3'b111) & (OPREG[2:0] == 3'b110) & (op3_feld[7:4] != 4'hA); // valid for all incl. CUSTOM + + // +++++++++++++ Evaluation for 2 and 3 byte opcodes ++++++++++++++++++ + + // for one byte opcodes special treatmant neccessary + assign opc_bits = op_3byte ? op3_feld : op2_feld; + + assign op_ok = (op_1byte | op_12byte | op_2byte | op_3byte | exception) & ~stop; // used for computation of USED + + always @(posedge BCLK) if (PHASE_0) op_feld_reg <= opc_bits; + assign op_feld = PHASE_0 ? opc_bits : op_feld_reg; // constant for all following cycles + + // Evaluation of op_feld : + + assign atys = op_feld[47:45]; // [2] : TOS=>(SP), [1] : Ri => (Ri), [0] : 1=access of memory + assign atyd = op_feld[44:42]; // [2] : TOS=>(SP), [1] : Ri => (Ri), [0] : 1=access of memory + assign long = op_feld[41]; + assign src2_flag = op_feld[40]; + assign dest_flag = op_feld[39]; + + assign src_1 = {1'b0,op_feld[38:33]}; + assign src_2 = {1'b0,op_feld[32:27]}; + assign src1_le = op_feld[26:25]; + assign src2_le = op_feld[24:23]; + assign acc1 = (op_feld[22:21] != 2'b00) | atys[1]; // external access Source1 or "addr" : Reg => (Reg) + assign acc2 = (op_feld[17:16] != 2'b00) | atyd[1]; // external access Source2 or "addr" : Reg => (Reg) + assign wlor = dest_flag & ~acc2; + assign idx_n = {1'b0,(op_feld[22:20] == 3'b111)} + {1'b0,(op_feld[17:15] == 3'b111)}; // Index : 0,1 or 2 + assign idx = (idx_n != 2'b00); // Index is active + assign n_idx = idx_n - 2'b01; + + // The field otype is used only in Phase 0 + assign otype = exception ? 2'b11 : ((op_1byte | op_12byte) ? 2'b01 : opc_bits[12:11]); // string opcodes use code 2'b10 + + assign opera = op_feld[10:0]; + + assign dest_r = src_2[5:0]; + assign dest_rl = {dest_r[5:1],1'b0}; + + // +++++++++++++++++++++++++ Coprocessor operations field ++++++++++++++++++++++++++++++ + + always @(posedge BCLK) if (PHASE_0) COP_OP <= OPREG[23:0]; + + // +++++++++++++++++++++++++ Special signals for LMR and CINV ++++++++++++++++++++++++++ + // op_lmr is constant = parameter + + assign STOP_IC = (phase_reg == 8'h74) | (phase_reg == 8'h75); + + // CINV uses Register x'30 - x'37 : CINV = 110... , LMR = 001... otherwise CFG + always @(posedge BCLK) if (PHASE_0) lmrreg <= op_3byte ? {{2{OPREG[13]}},~OPREG[13],OPREG[17:15]} : 6'h1C; + + always @(posedge BCLK) no_init <= (lmrreg[5:4] == 2'b00) & (lmrreg[3:1] != 3'b110); // LMR waits for INIT at PTB0/1 + // a_ivar = "Addresse IVAR0/1" + always @(posedge BCLK) a_ivar <= STOP_IC; // Phase 74 & 75, is used at INFO_AU together with IC_READ + + // CINV detection for IC_CACHE + always @(posedge BCLK) + if (PHASE_0) cinv_flag <= OPREG[13] & (OPREG[7:0] == 8'h1E); + else cinv_flag <= cinv_flag & ~phase_reg[7]; // reset at exception + + assign ENA_HK = ~(cinv_flag & STOP_IC); // always "1", if CINV then "0" + + // +++++++++++++++++++++++++ USER flag for MOVUS & MOVSU ++++++++++++++++++++++++ + + always @(posedge BCLK) + if (PHASE_0) m_ussu <= (~OPREG[13] & (OPREG[11:10] == 2'b11) & (OPREG[7:0] == 8'hAE)); + else m_ussu <= m_ussu & ~phase_reg[7]; // reset at exception + + always @(posedge BCLK) if (PHASE_0) m_usel <= OPREG[12]; + + // +++++++++++++++++++++++++ USER flag for RDVAL & WRVAL ++++++++++++++++++++++++ + + always @(posedge BCLK) + if (PHASE_0) rwval_flag <= (OPREG[13:11] == 3'd0) & (OPREG[7:0] == 8'h1E); + else rwval_flag <= rwval_flag & ~phase_reg[7]; // reset at exception + + always @(posedge BCLK) if (PHASE_0) wrval_flag <= OPREG[10]; // Difference RDVAL=0 and WRVAL=1 + + // +++++++++++++++++++++++++ Flags for CBIT/I+SBIT/I+IBIT +++++++++++++++++++++++ + + assign rw_bit = (op_feld_reg[7:4] == 4'd6) & ((~op_feld_reg[3] & op_feld_reg[1]) | (op_feld_reg[3:0] == 4'hE)); + assign op_ilo = rw_bit & op_feld_reg[0]; // Interlocked : CBITI and SBITI + + // +++++++++++++++++++++++++++++ Operations for String processing +++++++++++++++++ + // Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2 + + assign st_src = {STRING[1:0],5'b1010_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1000}; // [15] = BACKWARD + assign st_src2 = {STRING[1:0],5'b1010_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1011}; // Reuse EA + assign st_dest = {STRING[1:0],5'b0110_0,(op_feld_reg[15] & ~kurz_st),STRING[1:0],9'b0_0000_1011}; // Reuse EA + assign st_trde = {2'b00, 5'b0110_0, op_feld_reg[15], 2'b00, 9'b0_0000_1000}; // after Translate to Dest + assign st_trs2 = {STRING[1:0],5'b1010_0, op_feld_reg[15], STRING[1:0],9'b0_0000_1000}; // after Match to SRC2 + assign st_len = {STRING[1:0],17'b0000_0000_0_0000_0000}; // length important for qw_flag + + // Signals of DETOIP go to I_PFAD + always @(posedge BCLK) if (PHASE_0) kill_opt <= ~OPREG[7] & (OPREG[17:15] != 3'b000); // watch difference of MOVM and MOVS + assign ph_match = (phase_reg[7:4] == 4'hD) & (phase_reg[2:0] == 3'd7); // Phase D7 and DF + + assign op_str = {op_feld_reg[10:8],6'b0101_00,op_feld_reg[1],1'b1}; // Opcode 8'h51 or 8'h53; + assign op_scp = {op_feld_reg[10:8],8'h41}; // normal CMPi + assign ph_str = {4'hC,op_feld_reg[1],3'b001}; // Phase 8'hC1 (MOVS/M) or 8'hC9 (CMPS/M) + + always @(posedge BCLK) kurz_st <= (phase_reg == 8'h65) | (kurz_st & ~PHASE_0); // Flag for MOVM/CMPM + always @(posedge BCLK) if (PHASE_0) cmps_flag <= ~OPREG[7] & (OPREG[11:10] == 2'b01); // Flag for CMPS + always @(posedge BCLK) if (PHASE_0) skps_flag <= ~OPREG[7] & (OPREG[11:10] == 2'b11); // Flag for SKPS + always @(posedge BCLK) if (PHASE_0) mt_flag <= ~OPREG[7] & (OPREG[17] | OPREG[15]); // Flag for Match and Translate + + assign wstr0 = {{4{kurz_st}},2'b00}; + assign wstr1 = {{4{kurz_st}},2'b01}; + assign wstr2 = {{4{kurz_st}},2'b10}; + assign rstr0 = {1'b0,wstr0}; + assign rstr1 = {1'b0,wstr1}; + assign rstr2 = {1'b0,wstr2}; + + // +++++++++++++++++++++++++++++++++++ Index processing +++++++++++++++++++++++++++++++++++++++++ + + assign phase_idx = (phase_reg == 8'h02) | (phase_reg == 8'h50); + + assign idx_bytes = idx_1[2] ? OPREG[15:0] : {OPREG[7:0],OPREG[7:0]}; // here last access of OPREG + always @(posedge BCLK) if (phase_idx) idx_reg <= idx_bytes; + assign idx_feld = (phase_idx) ? idx_bytes : idx_reg; + + // +++++++++++++++++++++++++++++++++++ The big state machine ++++++++++++++++++++++++++++++++++++ + + // Hints : + // 1. At short-op SRC1 is out of memory to use TEMP + // 2. At SRC2 rmw suppresed TOS and changed it to (SP) + // 3. The Long-operation path takes the dest_r address to write if WR_REG activ + // 4. It is ok, that an extra cycle for the read of the index registers is needed - then data could be written ins Out register + + // Source 1 + + assign idx_1 = {1'b0,(op_feld[22:20] == 3'b111),op_feld[19:18]}; + assign src1_addr = idx_1[2] ? idx_feld[7:3] : op_feld[22:18]; + assign stack = {1'b0,stack_sel[s_user],3'b110,s_user,1'b1}; + assign usp_1 = src1_addr[0] ? stack : {5'b0_0110,src1_addr[1:0]}; + assign src_1l = {src_1[6:1],1'b0}; + assign pop_1 = {2'b00,src1_le,9'h108}; // SP update, DISP=0 and POST + assign mpoi_1 = (src1_addr[4:2] == 3'b100) | (src1_addr == 5'h16); // Pointer in memory always DWord + assign auop_s = atys[0] ? 4'b1011 : 4'b0010; // Only make effective address ? + assign src1_tos = (op_feld[22:18] == 5'h17) & ~atys[2] ? 2'b11 : 2'b00; // Source 1 is true TOS + + // Nextfield : 11=DISP read + // Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2 + always @(*) + casex (src1_addr) // RWLF IDX ADDR_F NEUP SRC_REG NEXT + // Special case which is only valid at INDEX or "addr" : REG -> ADDR , DISP=0 : starts immediate at read + 5'b00xxx : gen_src1 = {auop_s, idx_1,9'h000,8'h07,4'h0,src1_addr[2:0],3'b000,atys[0]}; + // Register relativ : 0(R0) + 5'b01xxx : gen_src1 = {auop_s, idx_1,9'h000,8'h07,4'h0,src1_addr[2:0],3'b111,atys[0]}; + // Memory relativ : 0(0(SB)) + 5'b100xx : gen_src1 = {4'b1011,4'h0, 9'h000,8'h06,usp_1, 4'b1111}; // 1. access always full + // Immediate + 5'b10100 : gen_src1 = (src1_le == 2'b11) ? + {4'h0, 4'h0, 9'h000,8'h0B,src_x, 1'b1,2'b10,1'b0} // load in DWord pieces + : {4'h0, 4'h0, 9'h000,8'h07,src_x, 1'b1,src1_le,1'b0}; + 5'b10101 : gen_src1 = {auop_s, idx_1,9'h002,8'h07,src_x, 3'b111,atys[0]}; // Absolut Addressing + 5'b10110 : gen_src1 = {4'b1011,4'h0, 9'h014,8'h05,7'h1F, 4'b0001}; // External with MOD Register +4 + 5'b10111 : gen_src1 = (idx_1[2] | atys[2]) ? // Access class "addr" ? + {auop_s, idx_1,9'h000,8'h07,stack, 3'b000,atys[0]} // 0(SP) : no TOS flag + : {4'b1011,pop_1, 8'h07,stack, 4'b0001}; // TOS + // Memory Space : 0(SB) + 5'b110x0 : gen_src1 = {auop_s, idx_1,9'h000,8'h07,5'b0_0110,src1_addr[1:0],3'b111,atys[0]}; // SB+FP + 5'b11001 : gen_src1 = {auop_s, idx_1,9'h000,8'h07,stack, 3'b111,atys[0]}; // SP + 5'b11011 : gen_src1 = {auop_s, idx_1,9'h001,8'h07,src_x, 3'b111,atys[0]}; // PC relativ + default : gen_src1 = 36'hx_xxxx_xxxx; // don't care + endcase + + assign adrd1 = {(mpoi_1 ? 2'b10 : src1_le),gen_src1[35:19]}; // Addressfield : 19 Bits + assign phrd1 = gen_src1[18:11]; // next phase + assign rega1 = gen_src1[10:4]; // Source 1 Register + assign irrw1 = {4'b0,idx_feld[2:0]}; // Index-Register + assign nxrd1 = gen_src1[3:0]; // Memory/Disp/Immediate operation + assign exr11 = {2'b10 ,4'b1011,4'h0 ,9'h080}; // 2. access external with Mem.-Pointer + 4* Disp + assign exr12 = {src1_le,auop_s,idx_1,9'h000}; // for Memory Relative and EXT in last step + + // Source 2 resp. Destination + + assign rmw = src2_flag & dest_flag; + assign idx_2 = {1'b0,(op_feld[17:15] == 3'b111),op_feld[14:13]}; // 4 bits + assign src2_addr = idx_2[2] ? idx_feld[15:11] : op_feld[17:13]; + assign usp_2 = src2_addr[0] ? stack : {5'b0_0110,src2_addr[1:0]}; + assign src_2l = {src_2[6:1],1'b0}; + assign mpoi_2 = (src2_addr[4:2] == 3'b100) | (src2_addr == 5'h16); // Pointer in memory always DWord + assign auop_d = atyd[0] ? 4'b1011 : 4'b0010; // Only make effective address ? + + // The next assessment processes TOS separated for PUSH and POP + assign tos_oper = src2_flag ? + {2'b00,atyd[0],2'b01,atyd[0],2'b00,src2_le,7'b1_0000_10, src1_tos,4'h7,stack,3'b0,atyd[0]} // POP + : {1'b0,atyd[0],3'b001,atyd[0],4'h0, 1'b1,2'b10,src2_le,2'b0,src1_tos,4'h7,stack,3'b0,atyd[0]}; // PUSH + + // Nextfield : 11=DISP read + // Address field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2 + always @(*) + casex (src2_addr) // RW:W RW:R LF IDX ADDR_F NEUP SRC_REG NEXT + // Special case which is only valid at INDEX or "addr" : REG -> ADDR , DISP=0 : starts immediate at read + 5'b00xxx : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,4'h0,src2_addr[2:0],3'b000,atyd[0]}; + // Register relativ : 0(R0) + 5'b01xxx : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,4'h0,src2_addr[2:0],3'b111,atyd[0]}; + // Memory relativ : 0(0(SB)) + 5'b100xx : gen_src2 = {2'b10,2'b10,2'b11,4'h0, 9'h000,4'h6,usp_2, 4'b1111}; // 1. access always full + // Immediate + 5'b10100 : gen_src2 = (src2_le == 2'b11) ? + {2'b00,2'b00,2'b00,4'h0, 9'h000,4'hB,src_x, 1'b1,2'b10,1'b0} // load in DWord pieces + : {2'b00,2'b00,2'b00,4'h0, 9'h000,4'h7,src_x, 1'b1,src2_le,1'b0}; + 5'b10101 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h002,4'h7,src_x, 3'b111,atyd[0]}; // Absolut with special coding + 5'b10110 : gen_src2 = {2'b10,2'b10,2'b11,4'h0, 9'h014,4'h5,7'h1F, 4'b0001}; // External with MOD Register +4 + 5'b10111 : gen_src2 = (idx_2[2] | rmw | atyd[2]) ? + {1'b0,atyd[0],auop_d, idx_2,7'b0_0000_00,src1_tos,4'h7,stack, 3'b000,atyd[0]} // 0(SP) : TOS + DISP=0 + : tos_oper; // TOS : 2 cases for PUSH and POP + // Memory Space + 5'b110x0 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,5'b0_0110,src2_addr[1:0],3'b111,atyd[0]}; + 5'b11001 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h000,4'h7,stack, 3'b111,atyd[0]}; + 5'b11011 : gen_src2 = {1'b0,atyd[0],auop_d, idx_2,9'h001,4'h7,src_x, 3'b111,atyd[0]}; // PC relativ + default : gen_src2 = 34'hx_xxxx_xxxx; // don't care + endcase + + assign adrd2 = {(mpoi_2 ? 2'b10 : src2_le),gen_src2[31:15]}; + assign adwr2 = {(mpoi_2 ? 2'b10 : src2_le),gen_src2[33:32],gen_src2[29:15]}; + assign phrd2 = {4'h1,gen_src2[14:11]}; // Phase for Read Source 2 + assign phwr2 = {4'h2,gen_src2[14:11]}; // Phase for Write Destination + assign rega2 = gen_src2[10:4]; + assign nxrw2 = gen_src2[3:0]; + assign irrw2 = {4'b0,idx_feld[10:8]}; + assign re_wr = {src2_le,4'b0101,4'h0, 9'h003}; // REUSE Address : Write of rmw + assign exr22 = {src2_le,atyd[0],1'b0,1'b1,atyd[0],idx_2,9'h000}; // for Memory Relative and EXT in last step + assign exw22 = {src2_le,1'b0,atyd[0],1'b1,atyd[0],idx_2,9'h000}; // for Memory Relative and EXT in last step + + // Special case : + + assign quei1 = acc1 ? imme : src_1l; // 8B passing either from register or from extern + // 8B is requested from both operands but only to certain times + assign qword = (phase_reg[7:4] != 4'h0) ? (src2_le == 2'b11) : (src1_le == 2'b11); + assign quet1 = acc1 ? temp_h : src_1; // select source during calculation + + // Output data of state machine + // LOAD if PULS if simple + // NEXT -> ENABLE ENABLE out + // [66:48] 19 ADDR : X ; Op-length REUSE RD/WR etc. + // [47:40] 8 new phase X + // [39:33] 7 SRC1 X + // [32:26] 7 SRC2 X + // [25] 1 WREN X + // [24:19] 6 DEST X + // [18:8] 11 OPER X + // [7:6] 2 START X + // [5:4] 2 LD_OUT X + // [3] 1 ID Load X + // [2:1] 2 ID Type X ; 0 = DISP + // [0] 1 MEM Access X + + // State acc2-src2_flag-dest_flag + // no SRC2 x 0 x + // SRC2=REG 0 1 0 ; CMP+TBIT + // SRC2=REG 0 1 1 ; all else + // SRC2=MEM 1 1 0 ; CMP+TBIT + // SRC2=MEM 1 1 1 ; all else + + // Input data for state machine + + // 8 phase_reg : phase of state machine + // 2 otype : Opcode type + + // 1 idx : Index is available : 1 or 2 , only PHASE_0 + // 1 short_op : short opcodes like ADDQ + // 1 long : "long" opcode + // 1 qword : 8B access at Source (Exception DEI+MEI) + + // 1 acc1 : Reg/Extern SRC1 + // 1 acc2 : Reg/Extern SRC2 + // 1 src2_flag : the 2. operand is being read + // 1 dest_flag : there is a target operand : only CMP and TBIT have none + + assign phase_ein = abbruch ? 8'h00 : phase_reg; + + always @(*) // "_" "_" + casex ({phase_ein,otype, idx,short_def,long,qword, acc1,acc2,src2_flag,dest_flag}) + {8'h00,10'b00_1xxx_xxxx}: // Index must be loaded : phase 2 : in any case load TEMP for Short-Op and generate LD_OUT + new_op = short_op ? // START LD_OUT + {addr_nop,8'h02, imme, src_x, 1'b1,temp_h, op_sho, 2'b00,2'b10, 1'b1,n_idx,1'b0} + : {addr_nop,8'h02, src_1,src_1l,1'b0,dest_x, opera, 2'b00,~src2_flag,2'b1_1,n_idx,1'b0}; + {8'h00,10'b00_01xx_x0xx}: // Short-Op to register, LD_OUT because of CMPQ + new_op = {addr_nop,goacb, imme, src_2,dest_flag,dest_r, opera, 2'b00,2'b10, 4'h0}; + {8'h00,10'b00_01xx_x11x}: // Short-Op : external operand read : SRC2 ! Data in TEMP ! Here no Index + new_op = {adrd2, phrd2, imme, rega2, 1'b1,temp_h, op_mov, 2'b00,2'b00, nxrw2}; + {8'h00,10'b00_01xx_x10x}: // MOVQ to Mem + new_op = {adwr2, phwr2, imme, rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2}; + {8'h00,10'b00_0000_00xx}: // simple register operation : dest_flag controls WREN, LD_OUT for CMP + new_op = {addr_nop,dowait,src_1,src_2, dest_flag,dest_r,opera, 2'b00,2'b10, 4'h0}; + {8'h00,10'b00_0001_00xx}: // "simple" Reg-Op of 8B, phase 8 after 2. DWord , not via LONG-path + new_op = {addr_nop,8'h08, src_1,src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'h0}; + {8'h00,10'b00_0010_00xx}: // long register operation i.e. DIV - phase 31 + new_op = {addr_nop,8'h1F, src_1,src_2, wlor,dest_r, opera, 2'b11,2'b00, 4'h0}; + {8'h00,10'b00_0011_001x}: // long register operation with QWORD - phase 26 then wait + new_op = {addr_nop,8'h1A, src_1,src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0}; + {8'h00,10'b00_00xx_1xxx}: // Source 1 in memory - first to read , here no Index + new_op = {adrd1, phrd1, src_x,rega1, 1'b0,dest_x, opera, 2'b00,2'b00, nxrd1}; + {8'h00,10'b00_00xx_011x}: // Source 2 in memory - first to read (Source 1 in register) + new_op = {adrd2, phrd2, src_x,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + {8'h00,10'b00_0000_0101}: // Source 1 store in Dest : "pass through" for MOV,NEG,ABS + new_op = {adwr2, phwr2, src_1,rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2}; + {8'h00,10'b00_0001_0101}: // Source 1 store in Dest : "pass through" for MOV,NEG,ABS for Long operands + new_op = //(op_feld[17:13] == 5'h17) ? // TOS : special case , first 8B out of Reg and then read SP + {addr_nop,8'h1C, src_1,src_1l,1'b0,dest_x, opera, 2'b00,2'b11, 4'h0}; + {8'h00,10'b00_0010_0101}: // SRC1 -> DEST with short operands + new_op = {addr_nop,8'h1F, src_1,src_x, 1'b0,dest_r, opera, 2'b11,2'b00, 4'h0}; + {8'h00,10'b00_0011_0x01}: // SRC1 -> DEST i.e. ROUNDLi + new_op = {addr_nop,8'h1F, src_1,src_1l,wlor,dest_r, opera, 2'b11,2'b00, 4'h0}; + + // Phase 2 : after read of Index nearly everything is repeated from PHASE_0 + {8'h02,10'bxx_x1xx_x11x}: // Short-Op : external operand read + new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + {8'h02,10'bxx_x1xx_x101}: // MOVQ to Mem, data is in Out-Register + new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + {8'h02,10'bxx_x0xx_1xxx}: // Source 1 in memory - first to read + new_op = {adrd1, phrd1, irrw1,rega1, 1'b0,dest_x, opera, 2'b00,2'b00, nxrd1}; + {8'h02,10'bxx_x0xx_011x}: // Source 2 in memory - first to read + new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + {8'h02,10'bxx_x00x_0101}: // Source 1 store in Dest : "pass through" , data is already in Out-Register + new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + {8'h02,10'bxx_x010_0101}: // SRC1 -> DEST with short operands + new_op = {addr_nop,8'h1F, src_1,src_x, 1'b0,dest_x, opera, 2'b11,2'b00, 4'h0}; + {8'h02,10'bxx_x011_0101}: // SRC1 -> DEST i.e. ROUNDLi + new_op = {addr_nop,8'h1F, src_1,src_1l,1'b0,dest_x, opera, 2'b11,2'b00, 4'h0}; + + // +++++++++++++++++ SRC1 operand loading +++++++++++++++++++ + + // Phase 5 : wait for data and Disp2 for External addressing : part 2 EA = (MOD+4)+4*DISP1 + // next phase fix : 6 + {8'h05,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h06, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 4'b1111}; + // Phase 6 : Memory-Pointer for Memory Relative and last access External + // next phase fix : 7 , add Index + {8'h06,10'bxx_xxxx_xxxx}: new_op = {exr12, 8'h07, irrw1,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 3'b111,atys[0]}; + + // Phase 7 : wait for final data , direct from PHASE_0 if TOS without Index + // next phase : if 8B data phase 8 is neccessary + // if SRC2=REG execution started (otherwise store data in TEMP) and PHASE_0 + {8'h07,10'bxx_xx00_x0xx}: // into Register , short operation execution , but LD_OUT for PSR Update ! dest_flag => WREN + new_op = {addr_nop,endea, imme, src_2, dest_flag,dest_r,opera, 2'b00,2'b10, diacb}; + {8'h07,10'bxx_xx01_x0xx}: // into Reg but with a step om between for ABSL etc. : phase 8 + new_op = {addr_nop,8'h08, imme, src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'h0}; + {8'h07,10'bxx_xx10_x0xx}: // execute long operation , wait in phase 31 + new_op = {addr_nop,8'h1F, imme, src_2, wlor,dest_r, opera, 2'b11,2'b00, 4'h0}; + {8'h07,10'bxx_xx11_xx0x}: // execute long operation : 2. operand only Dest , load LSD , phase 24 , wait in phase 31 + new_op = {addr_nop,8'h18, imme, src_x, 1'b1,temp_l, op_mov, 2'b01,2'b00, 4'h0}; + {8'h07,10'bxx_xx11_x01x}: // lange Operation ausfuehren , LSD laden , phase 25 , warten in phase 31 + new_op = {addr_nop,8'h19, imme, src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0}; + {8'h07,10'bxx_xxx0_x11x}: // Data into TEMP , read 2. operand , is there Index ? Yes -> phase 15 + new_op = idx_2[2] ? + {addr_nop,8'h0F, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0} + : {adrd2, phrd2, imme, rega2, 1'b1,temp_h, op_mov, 2'b00,2'b00, nxrw2}; + {8'h07,10'bxx_xxx1_x11x}: // 8B data in TEMP , step in between then 2. Op read : phase 10 - can only be "long" operation + new_op = {addr_nop,8'h0A, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + {8'h07,10'bxx_xx00_x101}: // something like ABSi , execute and store (LD_OUT) + new_op = idx_2[2] ? + {addr_nop,8'h10, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'h0} + : {adwr2, phwr2, imme, rega2, 1'b0,dest_x, opera, 2'b00,2'b10, nxrw2}; + {8'h07,10'bxx_xx01_x101}: // ABS etc. : LSD data over SRC2 in 2. OUT-Reg , MSD data see opcode ABS/NEG/MOV , phase 9 + new_op = {addr_nop,8'h09, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'h0}; + {8'h07,10'bxx_xx10_x101}: // opcodes like MOVFL + new_op = {addr_nop,8'h1F, imme, src_x, 1'b0,dest_x, opera, 2'b11,2'b00, 4'h0}; + + // Phase 8 : 2. part of 64 bit data : can be reached from PHASE_0 if 8B data + {8'h08,10'bxx_xxxx_xxxx}: new_op = {addr_nop,endea, quei1,src_x, 1'b1,dest_rl, op_mov, 2'b00,2'b00, diacb}; + // Phase 9 : step in between to get data in OUT-Reg Low , SRC1 is not possible + {8'h09,10'bxx_xxxx_xxxx}: // afterwards to data write + new_op = {addr_nop,8'h10, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b01, 4'h0}; + // Phase 10 : LSD data write in TEMP , source can be IMME data to + {8'h0A,10'bxx_xxxx_xxxx}: // 8B , after TEMP there can only be a 2. operand + new_op = idx_2[2] ? + {addr_nop,8'h0F, imme, src_x, 1'b1,temp_l, op_mov, 2'b00,2'b00, 4'h0} + : {adrd2, phrd2, imme, rega2, 1'b1,temp_l, op_mov, 2'b00,2'b00, nxrw2}; + + // Phase 11 : wait for 8B IMME data : switch over at address decoder , qword flag is for sure "1" + {8'h0B,10'bxx_xx0x_x0xx}: // into Reg with step in between for ABSL etc. : phase 12 + new_op = {addr_nop,8'h0C, imme, src_x, 1'b1,dest_r, opera, 2'b00,2'b00, 4'b1100}; + {8'h0B,10'bxx_xx1x_x01x}: // execute long operation , load LSD , phase 25 , wait in phase 31 + new_op = {addr_nop,8'h19, imme, src_2, 1'b0,dest_r, opera, 2'b01,2'b00, 4'b1100}; + {8'h0B,10'bxx_xxxx_x11x}: // 8B data into TEMP , step in between then read 2. Op : phase 10 - can only be "long" operation + new_op = {addr_nop,8'h0A, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'b1100}; + {8'h0B,10'bxx_xx0x_x10x}: // ABS etc. : LSD data via SRC2 into 2. OUT-Reg , MSD data see opcode ABS/NEG/MOV , phase 9 + new_op = {addr_nop,8'h09, imme, src_x, 1'b0,dest_x, opera, 2'b00,2'b10, 4'b1100}; + {8'h0B,10'bxx_xx1x_xx0x}: // MOVLF with 8B IMME data ? Must be possible, the end in phase 24 like SRC1=MEM + new_op = {addr_nop,8'h18, imme, src_x, 1'b1,temp_l, op_mov, 2'b01,2'b00, 4'b1100}; + // Phase 12 : wait for 2. part of 64 bit IMME data : after phase 0 + {8'h0C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,endea, imme ,src_x, 1'b1,dest_rl, op_mov, 2'b00,2'b00, diacb}; + + // Phase 15 : secure in TEMP with Index continue and read 2. operand + {8'h0F,10'bxx_xxxx_xxxx}: new_op = {adrd2, phrd2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + // Phase 16 : after LD_OUT continue with Index and store 1. operand + {8'h10,10'bxx_xxxx_xxxx}: new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + + // +++++++++++++++++ SRC2 operand loading : phase SRC1 + 16 +++++++++++++++++++ + + // Phase 21 : wait for data and Disp2 for external addressing : part 2 EA = (MOD+4)+4*DISP1 + // next phase fix : 22 + {8'h15,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h16, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 4'b1111}; + // Phase 22 : Memory-Pointer for Memory Relative and last access external + // next phase fix : 23 , add Index + {8'h16,10'bxx_xxxx_xxxx}: new_op = {exr22, 8'h17, irrw2,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 3'b111,atyd[0]}; + + // Phase 23 : wait for final data , direct from PHASE_0 if TOS without Index + // next phase : if 8B data phase 24 is used + {8'h17,10'bxx_xx0x_xxx1}: // execute short operation and write data into memory , no WREN -> phase 39 ACC_DONE + new_op = {re_wr, 8'h27, quet1,imme , 1'b0,dest_r, opera, 2'b00,2'b10, 4'b0001}; + {8'h17,10'bxx_xx0x_xxx0}: // execute short operation , no WREN -> phase 0 , CMP(+TBIT) + new_op = {addr_nop,endea, quet1,imme , 1'b0,dest_r, opera, 2'b00,2'b10, diacb}; + {8'h17,10'bxx_xx10_xxxx}: // execute long operation , wait in phase 31 + new_op = {addr_nop,8'h1F, quet1,imme , wlor,dest_r, opera, 2'b11,2'b00, 4'h0}; + {8'h17,10'bxx_xx11_xxxx}: // execute long operation , load LSD in phase 24 + new_op = {addr_nop,8'h18, quet1,imme , 1'b0,dest_r, opera, 2'b01,2'b00, 4'h0}; + // Phase 24 : load 2. part of 64 bit data : with and without wait - from 28 the phase waits , from 23 not + {8'h18,10'bxx_xxxx_0xxx}: // execute long operation , wait in phase 31 + new_op = {addr_nop,8'h1F, src_1l,imme, wlor,dest_r, opera, 2'b10,2'b00, 4'h0}; + {8'h18,10'bxx_xxxx_1xxx}: // execute long operation , wait in phase 31 , data from TEMP, used also for ROUNDLi + new_op = {addr_nop,8'h1F, rtmpl,imme, wlor,dest_r, opera, 2'b10,2'b00, 4'h0}; + // Phase 25 : load 2. part of 64 bit data : SRC1 from memory and SRC2 from Reg + {8'h19,10'bxx_xxxx_xxxx}: // execute long operation , wait in phase 31 + new_op = {addr_nop,8'h1F, imme, src_2l,wlor,dest_r, opera, 2'b10,2'b00, 4'h0}; + // Phase 26 : load 2. part of 64 bit data : SRC1 from Reg and SRC2 from Reg + {8'h1A,10'bxx_xxxx_xxxx}: // execute long operation , wait in phase 31 + new_op = {addr_nop,8'h1F, src_1l,src_2l,wlor,dest_r, opera, 2'b10,2'b00, 4'h0}; + + // Phase 27 : wait for 8B IMME data : switch over at address decoder , qword flag is for sure "1" + {8'h1B,10'bxx_xxxx_xxxx}: // execute long operation , load LSD in phase 24 + new_op = {addr_nop,8'h18, quet1,imme , 1'b0,dest_r, opera, 2'b01,2'b00, 4'b1100}; + + // +++++++++++++++++ special case ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Phase 28 : TOS with 8B SRC1 operand , no Index ! Jump to phase 39 + {8'h1C,10'bxx_xxxx_xxxx}: // store Source 1 in Dest : "pass through" for MOV,NEG,ABS + new_op = {adwr2, phwr2, src_x,rega2, 1'b0,dest_x, opera, 2'b00,2'b00, nxrw2}; + // +++++++++++++++++ close operation : write out DEST , TOS update +++++++++++++++++++ + + // Phase 31 : wait for DONE of long operation + {8'h1F,10'bxx_xxxx_xxx0}: // CMP done -> phase 0 + new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b10, 4'h0}; // no ACB + {8'h1F,10'bxx_xxxx_x0x1}: // operation closed , data into register + new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b00, 4'h0}; // no ACB + {8'h1F,10'bxx_xxxx_x101}: // operation closed , data into memory - first calculate address phase 32+x + new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_r, opera, 2'b00,2'b00, nxrw2}; + {8'h1F,10'bxx_xxxx_x111}: // operation closed , data into memory - address reuse phase 39 ACC_DONE + new_op = {re_wr, 8'h27, src_x,src_x, 1'b0,dest_r, opera, 2'b00,2'b00, 4'b0001}; + + // Destination address calculate + // Phase 37 : wait for data and Disp2 for External addressing : part 2 EA = (MOD+4)+4*DISP1 + // next phase fix : 38 + {8'h25,10'bxx_xxxx_xxxx}: new_op = {exr11, 8'h26, src_x,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 4'b1111}; + // Phase 38 : Memory-Pointer for Memory Relative and letzter Zugriff External + // next phase fix : 39 , add Index and write + {8'h26,10'bxx_xxxx_xxxx}: new_op = {exw22, 8'h27, irrw2,imme , 1'b0,dest_x, opera, 2'b00,2'b00, 4'b1111}; + + // Phase 39 : wait for ACC_DONE : consequent numbering : 7+32 + {8'h27,10'bxx_xxxx_xxxx}: // now operation closed , only ACB could follow + new_op = {addr_nop,endea, src_x,src_x, 1'b0,dest_x, opera, 2'b00,2'b00, diacb}; + + // +++++++++++++++ special case : ACB to Reg is to fast ! One wait cycle for ZERO-Flag + {8'h28,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h01,src_x, src_x, 1'b0,dest_x, opera, 2'b00,2'b00, 4'b1110}; + + // +++++++++++++++ The other opcodes are following ++++++++++++++++++ + + {8'h00,10'b01_xxxx_xxxx}: new_op = {new_addr,new_ph,new_regs, 1'b0,dest_x, op_mov, new_nx}; // 1 Byte Opcodes + + // Phase 1 : used for Bcond and ACB : + {8'h01,10'bxx_xxxx_xxxx}: new_op = (ex_br_op[1] | jsr_flag) ? // BSR or JSR ? + {push_op, 8'h27, imme, stack, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'b0001} // wait at end + : {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + + // Phase 42 : RET : read of PC from Stack and DIN via SRC1 to PC + {8'h2A,10'bxx_xxxx_xxxx}: new_op = {adddisp, 8'h2B, imme, src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'hE}; + // Phase 43 : RET : Displacement add to Stack. Attention : "imme" important to keep source constant for PC + {8'h2B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h2C, imme, src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 44 : RET : Update of Stack : fixed phase + {8'h2C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + + // Phase 45 : ENTER Entry + {8'h2D,10'bxx_xxxx_xxxx}: new_op = {dispmin, 8'h2E, src_x,src_x, 1'b1,temp_l, op_adr, 2'b00,2'b00, 4'hE}; + // Phase 46 : ENTER Stack longer + {8'h2E,10'bxx_xxxx_xxxx}: new_op = {save_sp ,8'h31, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 48 : SAVE/ENTER : Init phase , phases 48 & 49 very similar + {8'h30,10'bxx_xxxx_xxxx}: new_op = save_reg ? + {push_op, 8'h31, saver,stack, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h1} // 1. load SP=>EA + : {addr_nop,8'h00, rtmpl,src_x,new_fp,frame[5:0],op_mov, 2'b00,2'b00, 4'h0}; // At ENTER FP Update + // Phase 49 : SAVE/ENTER : at the same time memory access and detection of next Reg + {8'h31,10'bxx_xxxx_xxxx}: new_op = save_reg ? + {push_ea, 8'h31, saver,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h1} // one more + : {addr_nop,8'h00, rtmpl,src_x,new_fp,frame[5:0],op_mov, 2'b00,2'b00, 4'h0}; // At ENTER FP Update + + // Phase 50 : RESTORE/EXIT Entry + {8'h32,10'bxx_xxxx_xxxx}: new_op = save_reg ? + {pop_op, 8'h33, src_x,stack, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1} + : {pop_fp, ppfp, src_x,frame, 1'b0,dest_x, op_mov, 2'b00,2'b00, 3'h0,new_fp}; + // Phase 51 : RESTORE/EXIT next reg + {8'h33,10'bxx_xxxx_xxxx}: new_op = save_reg ? + {next_po, 8'h33, imme, src_x, 1'b1,resto, op_mov, 2'b00,2'b00, 4'h1} + : {pop_fp, ppfp, imme, frame, 1'b1,resto, op_mov, 2'b00,2'b00, 3'h0,new_fp}; + // Phase 52 : EXIT End + {8'h34,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, imme, src_x, 1'b1,frame[5:0], op_mov, 2'b00,2'b00, 4'h0}; + + // Phase 53 : CXP Entry : this opcode needs 12 States and 16 cycles minimum ... + {8'h35,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h36, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 54 : CXP : Store Address Link table + {8'h36,10'bxx_xxxx_xxxx}: new_op = {rdltab, 8'h37, src_x,rtmph, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'hE}; // EA Phase : DISP read + // Phase 55 : CXP : DISP is worked on, the return address => temp_l + {8'h37,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h38, imme, rtmph, 1'b1,temp_l, op_mov, 2'b00,2'b00, 4'h1}; // Access + // Phase 56 : CXP : Access to Link table => Result is MOD-Entry => store in temp_h + {8'h38,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h39, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 57 : CXP : store and PUSH MOD prepare , Entry from Exception Processing + {8'h39,10'bxx_xxxx_xxxx}: new_op = {push_op, 8'h3A, modul,stack, 1'b0,dest_x, op_wrp, 2'b00,2'b10, 4'h1}; + // Phase 58 : CXP : PUSH of MOD ongoing, PUSH PC prepare + {8'h3A,10'bxx_xxxx_xxxx}: new_op = {ea_push, 8'h3B, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0}; + // Phase 59 : CXP : New EA for PC + {8'h3B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h3C, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 60 : CXP : write of PC, calculate of Offset + {8'h3C,10'bxx_xxxx_xxxx}: new_op = {rmod_8, 8'h3D, rtmph,rtmph, 1'b1,temp_l, op_flip,2'b00,2'b00, 4'h1}; + // Phase 61 : CXP : read from (MOD:New+8) + {8'h3D,10'bxx_xxxx_xxxx}: new_op = {ea_min8, 8'h3E, imme, rtmpl, 1'b1,temp_l, op_add, 2'b00,2'b00, 4'h0}; // Reuse of EA + // Phase 62 : CXP : EA Phase of SB read , new PC calculated + {8'h3E,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h3F, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 63 : CXP : read of SB , new PC to ICache + {8'h3F,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h2F, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'h0}; // SB load + // Phase 47 : CXP : Last phase update of MOD prepare + {8'h2F,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, rtmph,src_x, 1'b1,modul[5:0], op_mov, 2'b00,2'b00, 4'h0}; // MOD load + + // Phase 64 : RXP Entry : POP of PC , full Access + {8'h40,10'bxx_xxxx_xxxx}: new_op = {pop_ru, 8'h41, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 65 : RXP : PC is read, next POP prepare + {8'h41,10'bxx_xxxx_xxxx}: new_op = {adddisp, 8'h42, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'hF}; + // Phase 66 : RXP : DISP is addeed to Stack and MOD is read + {8'h42,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h43, imme, src_x, 1'b1,modul[5:0], op_mov, 2'b00,2'b00, 4'h0}; + // Phase 67 : RXP : MOD is new + {8'h43,10'bxx_xxxx_xxxx}: new_op = {rmod_rxp,8'h44, rtmph,modul, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 68 : RXP : wait for SB data, parallel SP update + {8'h44,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'h0}; // SB load + + // Phase 69 : RETI : read of ICU for End-of-Interrupt Cycle , prepare read PC from Stack + {8'h45,10'bxx_xxxx_xxxx}: new_op = {pop_op, 8'h46, src_x,stack, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 70 : RETI/ RETT Entry : POP of PC , full Access + {8'h46,10'bxx_xxxx_xxxx}: new_op = {pop_ru, 8'h47, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 71 : RETI/RETT : PC is read, next POP prepare + {8'h47,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h48, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 72 : RETI/RETT : DISP is added to Stack , PSR load and MOD is loaded if DE off + {8'h48,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h49, imme, src_x, no_modul, op_ldp, 2'b00,2'b00, 4'h0}; + // Phase 73 : RETI/RETT : different paths + {8'h49,10'bxx_xxxx_xxxx}: new_op = de_flag ? + ( reti_flag ? + {addr_nop,8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'h4B, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} ) + : {rmod_rtt,8'h4B, rtmph,modul, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + // Phase 74 : RETI/RETT : one pause cycle if DE on + {8'h4A,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 75 : RETI/RETT : SB read if DE off + {8'h4B,10'bxx_xxxx_xxxx}: new_op = reti_flag ? + {addr_nop,8'h00, imme, src_x, 1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'h0} + : ( de_flag ? + {adddispn,8'h4E, src_x,ttstak,1'b0,dest_x, op_mov, 2'b00,2'b00, 4'hE} + : {adddispn,8'h4E, imme, ttstak,1'b1,6'h1A, op_mov, 2'b00,2'b00, 4'hE} ); + // Phase 78 : RETT : SP update + {8'h4E,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + + // +++++++++++++++ special wait states for PSR and the Cache/MMU system +++++++++++ + + // Phase 76 : PSR in Word case simple delay of 2 cycles : 1. cycle does nothing + {8'h4C,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h4D, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 77 : PSR in Word case simple delay of 2 cycles : 2. cycle does Restart of instruction processing + {8'h4D,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 79 : Wait for INIT_DONE from Cachesystem + {8'h4F,10'bxx_xxxx_xxxx}: new_op = (INIT_DONE | no_init) ? + {addr_nop,8'h4D, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'h4F, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + + // +++++++++++++++ Direct Exception procession similar to CXP ++++++++++++++++++++ + + // Phase 121 : CXP : store and PUSH PSR prepare , Entry of Exception Processing + {8'h79,10'bxx_xxxx_xxxx}: new_op = {push_op, 8'h7A, modul,stack, 1'b0,dest_x, op_wrp, 2'b00,2'b10, 4'h1}; + // Phase 122 : CXP : PUSH of PSR running, PUSH PC prepare - MOD like normal Exception-Flow + {8'h7A,10'bxx_xxxx_xxxx}: new_op = {ea_push, 8'h7B, rtmpl,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0}; + // Phase 123 : CXP : New EA for PC , Output of Interrupt-Vector and LOAD_PC generation, continue at standard exit + {8'h7B,10'bxx_xxxx_xxxx}: new_op = {save_sp, 8'h4A, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + + // +++++++++++++++ here comes the general Exception Processing ++++++++++++++++++ + + // Phase 0 : Entry with saving of PC_ARCHI and PSR + {8'h00,10'b11_xxxx_xxxx}: new_op = {save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00, 4'h0}; + // Phase 128 : different paths to three cases + {8'h80,10'bxx_xxxx_xxxx}: new_op = abo_int ? + {ai_next[30:4], src_x,src_x, 1'b1,temp_l, op_adr, 2'b00,2'b00, ai_next[3:0]} + : {get_vec, 8'h81, src_x,ibase, 1'b1,temp_l, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 129 : read of Exception-Vectors and store in TEMP_H , then continue at CXP if DE off + {8'h81,10'bxx_xxxx_xxxx}: new_op = de_flag ? + {addr_nop,8'h79, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'h39, imme, src_x, 1'b1,temp_h, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 130 : read of Interrupt-Vectors, Zero-Extension of Byte => TEMP_H + {8'h82,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h83, imme, src_x, 1'b1,temp_h, op_zex, 2'b00,2'b00, 4'h0}; + // Phase 131 : access of Exception-Vector + {8'h83,10'bxx_xxxx_xxxx}: new_op = (type_nmi | ~ivec_flag) ? // NMI or non-vectored INT ? + {get_vec, 8'h81, src_x,ibase, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1} + : {get_veci,8'h81, rtmph,ibase, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1}; + + // Phase 132 : ABORT : store TEAR + {8'h84,10'bxx_xxxx_xxxx}: new_op = {save_msr,8'h85, src_x,src_x, 1'b1,w_tear, op_adr, 2'b00,2'b00, 4'h0}; + // Phase 133 : store MSR + {8'h85,10'bxx_xxxx_xxxx}: new_op = (ssrc_flag | sdest_flag) ? + {addr_nop,rrepa, src_x,src_x, 1'b1,w_msr, op_adr, 2'b00,2'b00, 4'h0} + : {get_vec ,8'h81, src_x,ibase, 1'b1,w_msr, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 134 : reload of pointers for string opcodes : R2 Dest + {8'h86,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h87, rtmp1,src_x, 1'b1,6'h02, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 135 : reload of pointers for string opcodes : R1 Source + {8'h87,10'bxx_xxxx_xxxx}: new_op = {get_vec ,8'h81, rtmph,ibase, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h1}; + + // +++++++++++++++++ WAIT +++++++++++++++++++++++++++++++++ + {8'h88,10'bxx_xxxx_xxxx}: new_op = interrupt ? + {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} // wait ... + : {addr_nop,8'h88, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; // Loop + + // +++++++++++++++++ FLAG +++++++++++++++++++++++++++++++++ + {8'h89,10'bxx_xxxx_xxxx}: new_op = flag ? + {save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00, 4'h0} // TRAP + : {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; // continue + + // +++++++++++++++++ The Opcodes of Gruppe 2 +++++++++++++++ + + {8'h00,10'b10_0xxx_xxxx}: new_op = state_0; + // Now the case with Index , the Long Operand is copied to OUT + {8'h00,10'b10_1xxx_xxxx}: new_op = {addr_nop,8'h50, src_1,src_1l,1'b0,dest_x, opera, 2'b00,~src2_flag,2'b1_1,n_idx,1'b0}; + + {8'h5x,10'bxx_xxxx_xxxx}: new_op = state_group_50; // Gruppe 2 Opcodes + {8'h6x,10'bxx_xxxx_xxxx}: new_op = state_group_60; // Gruppe 2 Opcodes + + // that is only for CVTP : + {8'h73,10'bxx_xxxx_x0xx}: new_op = {addr_nop,8'h00, src_x,src_x, 1'b1,dest_r, op_adr, 2'b00,2'b00, 4'h0}; + {8'h73,10'bxx_xxxx_x1xx}: new_op = {adwr2, phwr2, irrw2,rega2, 1'b0,dest_x, op_adr, 2'b00,2'b10, nxrw2}; + + // that is only for LMR and CINV : + {8'h74,10'bxx_xxxx_xxxx}: new_op = (IC_READ | STOP_CINV) ? + {ivar_adr,8'h74, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} // wait ... + : {ivar_adr,8'h75, rtmph,src_x, 1'b1,lmrreg, op_lmr, 2'b00,2'b00, 4'h0}; // continue + {8'h75,10'bxx_xxxx_xxxx}: new_op = {ivar_adr,8'h4F, rtmph,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + + // +++++++++++++++++ The String Opcodes +++++++++++++++++++++ + + // Phase 192 : R0=0 ? + {8'hC0,10'bxx_xxxx_xxxx}: new_op = STRING[2] ? // Is R0<>0 ? + {st_src, ph_str,rstr1,rstr1, ~kurz_st,temp_h, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 193 : 1. part read of SRC-Register => EA + {8'hC1,10'bxx_xxxx_xxxx}: new_op = {st_len, 8'hC2, src_x,src_x, 1'b1,wstr1, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 194 : memory operation : read + {8'hC2,10'bxx_xxxx_xxxx}: new_op = mt_flag ? + {addr_nop,8'hD3, imme, src_x, 1'b1,temp_2, (op_feld_reg[14] ? op_zex : op_mov), + 2'b00,2'b00, 4'h0} + : {load_ea, 8'hC3, imme, rstr2, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0}; + // Phase 195 : Data in output register and at the same time R2 to EA + {8'hC3,10'bxx_xxxx_xxxx}: new_op = {st_dest, 8'hC4, rstr2,imme, ~kurz_st,temp_1, op_mov, 2'b00,2'b01, 4'h0}; + // Phase 196 : 1. part reuse EA and LSD of 8B data to Out-Register + {8'hC4,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hC5, src_x,src_x, 1'b1,wstr2, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 197 : memory operation : write + {8'hC5,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00, 4'h0}; + // Phase 199 : Test for End and Interrupt + {8'hC7,10'bxx_xxxx_xxxx}: new_op = (interrupt & ~kurz_st) ? + {save_pc, 8'h80, src_x,src_x, 1'b0,dest_x, op_psr, 2'b00,2'b00, 4'h0} // Interrupt ! + : ( STRING[2] ? // Is R0<>0 ? + {st_src, ph_str,rstr1,rstr1, ~kurz_st,temp_h, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} ); + // String Compare : + // Phase 201 : 1. part read of SRC-Register => EA + {8'hC9,10'bxx_xxxx_xxxx}: new_op = {st_len, 8'hCA, src_x,src_x, 1'b1,wstr1, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 202 : memory operation : read + {8'hCA,10'bxx_xxxx_xxxx}: new_op = mt_flag ? + {addr_nop,8'hDB, imme, src_x, 1'b1,temp_2, (op_feld_reg[14] ? op_zex : op_mov), + 2'b00,2'b00, 4'h0} + : ( skps_flag ? // SKPS read only String1 + {addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00, 4'h0} + : {load_ea, 8'hCB, imme, rstr2, 1'b1,temp_2, op_mov, 2'b00,2'b00, 4'h0} ); + // Phase 203 : Data to output register and at the same time R2 to EA + {8'hCB,10'bxx_xxxx_xxxx}: new_op = {st_src2, 8'hCC, rstr2,src_x, ~kurz_st,temp_1, op_mov, 2'b00,2'b00, 4'h0}; + // Phase 204 : 1. part reuse EA + {8'hCC,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hCD, src_x,src_x, 1'b1,wstr2, op_adr, 2'b00,2'b00, 4'h1}; + // Phase 205 : memory operation : read and prepare compare + {8'hCD,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hCE, rtmp2,imme, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}; + // Phase 206 : compare of data + {8'hCE,10'bxx_xxxx_xxxx}: new_op = STRING[3] ? // Elements equal ? Same as ACB_ZERO without delay of 1 cycle + {addr_nop,8'hC7, rstr0,src_x, 1'b1,wstr0, op_str, 2'b00,2'b00, 4'h0} + : ( kurz_st ? // at CMPM direct end + {addr_nop,8'h00, src_x,src_x, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h0} + : {addr_nop,8'hC8, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0} ); + // Phase 200 : reload of R1 at CMPS, prepare reload of R2 + {8'hC8,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'h00, rtmp1,src_x, 1'b1,6'h02, op_mov, 2'b00,2'b00, 4'h0}; + // String Options Match and Translate for MOVS + // Phase 211 : Test if Translate + {8'hD3,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[14] ? // Translate ? Translate Base is Register 3 + {st_trans,8'hD4, rtmp2,7'h03, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1} + : {addr_nop,8'hD7, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}; // Match + // Phase 212 : memory operation : read + {8'hD4,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hD5, imme, src_x, 1'b1,temp_2, op_mov, 2'b00,2'b10, 4'h0}; + // Phase 213 : Test if Match + {8'hD5,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[16] ? // Match ? Reference Value is Register 4 + {addr_nop,8'hD7, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0} + : {st_trde, 8'hC4, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0}; // back to MOVS + // Phase 215 : Match result evaluation + {8'hD7,10'bxx_xxxx_xxxx}: new_op = (STRING[3] ^ op_feld_reg[17]) ? // Not equal? (op_feld_reg[17] = 1 = UNTIL) + {load_ea, 8'hC3, rtmp2,7'h02, 1'b0,dest_x, op_mov, 2'b00,2'b10, 4'h0} // back to MOVS + : {addr_nop,8'h00, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0}; // Abort, R1 back + // String Options Match and Translate for CMPS and SKPS - to many options to get it in one state + // Phase 218 : Test if Translate + {8'hDB,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[14] ? // Translate ? Translate Base is Register 3 + {st_trans,8'hDC, rtmp2,7'h03, 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'h1} + : {addr_nop,8'hDF, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0}; // Match + // Phase 220 : memory operation : read + {8'hDC,10'bxx_xxxx_xxxx}: new_op = {addr_nop,8'hDD, imme, src_x, 1'b1,temp_2, op_mov, 2'b00,2'b10, 4'h0}; + // Phase 221 : Test if Match + {8'hDD,10'bxx_xxxx_xxxx}: new_op = op_feld_reg[16] ? // Match ? Reference value is Register 4 + {addr_nop,8'hDF, rtmp2,7'h04, 1'b0,dest_x, op_scp, 2'b00,2'b10, 4'h0} + : ( skps_flag ? // SKPS read only String1 + {addr_nop,8'hC7, 7'h00,src_x, 1'b1,6'h00, op_str, 2'b00,2'b00, 4'h0} // back to SKPS + : {st_trs2, 8'hCC, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0}); // back to CMPS + // Phase 223 : Match result evaluation + {8'hDF,10'bxx_xxxx_xxxx}: new_op = (STRING[3] ^ op_feld_reg[17]) ? // Not equal? (op_feld_reg[17] = 1 = UNTIL) + ( skps_flag ? // SKPS read only String1 + {addr_nop,8'hC7, 7'h00,src_x, 1'b1,6'h00, op_str, 2'b00,2'b00, 4'h0} // back to SKPS + : {st_trs2, 8'hCC, 7'h02,7'h02, 1'b1,temp_1, op_mov, 2'b00,2'b00, 4'h0} ) // back to CMPS + : {addr_nop,8'h00, rtmph,src_x, 1'b1,6'h01, op_mov, 2'b00,2'b00, 4'h0}; // Abort, R1 back + + default : new_op = 67'hx_xxxx_xxxx_xxxx_xxxx; + endcase + + // ++++++++++++++++++++++++ Deliver data of state machine ++++++++++++++++++++++++++++ + + // not all new_op bits are evaluated here ... + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) ACC_FELD[11:10] <= 2'b00; // RD WR + else if (next) ACC_FELD[11:10] <= new_op[64:63]; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) spupd_i <= 1'b0; // Stack Pointer Update + else if (next) spupd_i <= new_op[56]; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) oper_i <= 11'b0; + else if (next) oper_i <= new_op[18:8]; + + always @(posedge BCLK) + if (next) + begin + ACC_FELD[13:12] <= new_op[66:65]; // ASIZE[1:0] + ACC_FELD[8:0] <= {new_op[61:57],new_op[51:48]}; // FULLACC INDEX[3:0] POST CLRMSW SRC2SEL[1:0] + disp_sel <= new_op[55:52]; + wradr_i <= new_op[24:19]; + end + + always @(posedge BCLK) wmaske_i <= src2_le; // to simple ? + + always @(posedge BCLK) index_cmd <= (phase_reg == 8'h60); // that only for INDEX + + // WMASKE : SP always 32 Bit, opcodes in Format 1, Reg-Nr. >31 , INDEX opcodes and the CHECK operand too + assign WMASKE = {(spupd | format1 | wradr_i[5] | wmaske_i[1] | index_cmd | (oper_i[7:0] == 8'h83)),wmaske_i[0]}; + assign WRADR = spupd ? {~stack[5],stack[4:0]} : wradr_i; + assign WREN = (spupd | wren_i) & no_trap; + assign OPER = spupd ? op_adr : oper_i; + + always @(posedge BCLK) ACC_FELD[14] <= next & (new_op[64] | new_op[63] | new_op[62]); // NEWACC is important + always @(posedge BCLK) ACC_FELD[9] <= next & new_op[62]; // LDEA is only one pulse + + always @(posedge BCLK) START <= next ? new_op[7:6] : 2'b00; + always @(posedge BCLK) ldoreg <= next ? new_op[5:4] : 2'b00; // [1] = LD_OUT , [0] = LD_LDQ + always @(posedge BCLK) wren_i <= next & new_op[25] & ~new_op[7]; // only if no START[1] from Long-Op + + assign LD_OUT = {(ldoreg[1] & no_trap),ldoreg[0]}; // [1] = LD_OUT (for CMP too) , [0] = LD_LDQ + + assign spupd = spupd_i & ~wren_i & ~ldoreg[1] & ~spu_block; // no Stack Update if OUT Register load or already Write-Register + + assign do_long = new_op[7]; // START[1] for long_reg + + assign RDAA = {next,new_op[39:33]}; // Source 1 + assign RDAB = {next,new_op[32:26]}; // Source 2 + + always @(posedge BCLK) if (next) WR_REG = new_op[25] & new_op[7]; // START[1] : if WR then LONG path has register as Destination + + // special case : example is POLYL F2,TOS + always @(posedge BCLK) spu_block <= DONE & WR_REG; + + assign MMU_UPDATE[1] = (phase_reg == 8'h84) | (phase_reg == 8'h85); // serving the MMU at ABORT + + // only the real access gets USER Status : important for Memory Relative & External + always @(posedge BCLK) // MOVUS MOVSU RDVAL/WRVAL + if (ACC_FELD[14]) dc_user <= PSR[8] | (m_ussu & (m_usel ? (phase_reg == 8'h07) : (phase_reg == 8'h27))) | RWVAL[1]; + else dc_user <= dc_user & ~abort; + + always @(posedge BCLK) dc_ilo <= op_ilo & (phase_reg == 8'h59); + always @(posedge BCLK) ILO <= op_ilo & ((phase_reg == 8'h59) | (phase_reg == 8'h27)); + + assign RWVAL = {dc_ilo,(rwval_flag & (phase_reg == 8'h53)),wrval_flag}; // is used for DCACHE ILO too + + // Signals for the I_PATH + Debug + assign DETOIP = {pc_match,cmps_flag,ph_match,op_feld_reg[17],kill_opt,inss_op,exin_cmd,extract,bit_reg,kurz_st,dw_info,acb_reg,t2p}; + + // Signals for the ADDR_UNIT : [5]=RMW Signal + assign chk_rmw = (phase_reg == 8'h17) | (phase_reg == 8'h58) | ((phase_reg == 8'h59) & rw_bit); // right Gruppe 2 opcodes + assign INFO_AU = {no_trap,chk_rmw,(op_feld_reg[40:39] == 2'b11),RWVAL[1],(a_ivar & ~IC_READ),dc_user,disp_ok}; + + assign RESTART = (phase_reg == 8'h4D); + + // Signals to generate external STATUS + assign GENSTAT[2] = (phase_reg == 8'h88); // WAIT Signal + assign GENSTAT[1] = (phase_reg == 8'h82); // Interrupt Acknowlege Cycle + assign GENSTAT[0] = (phase_reg == 8'h45); // End-of-Interrupt Cycle + + // ++++++++++++++++++++ Here is the Sub-Modul for the opcodes of Gruppe 2 ++++++++++++++++ + + GRUPPE_2 reste_ops (.BCLK(BCLK), .PHASE_0(PHASE_0), .OPREG(OPREG[18:0]), .PHASE(phase_ein[3:0]), + .SRC_1(src_1), .SRC_2(src_2), .REGA1(rega1), .REGA2(rega2), .IRRW1(irrw1), .IRRW2(irrw2), + .ADRD1(adrd1), .ADRD2(adrd2), .EXR12(exr12), .EXR22(exr22), .PHRD1(phrd1[3:0]), .PHRD2(phrd2[3:0]), + .NXRD1(nxrd1), .NXRW2(nxrw2), .ACCA({acc1,1'b0,acc2,1'b0}), .OPERA(opera), + .STATE_0(state_0), .STATE_GROUP_50(state_group_50), .STATE_GROUP_60(state_group_60) ); + +endmodule diff --git a/src/m32632/DP_FPU.v b/src/m32632/DP_FPU.v new file mode 100644 index 0000000..761676a --- /dev/null +++ b/src/m32632/DP_FPU.v @@ -0,0 +1,1402 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: DP_FPU.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. PREPDATA Prepare data for the big multiplier +// 2. BCDADDER 4 bit BCD adder +// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor +// 4. DFPU_ADDSUB Double precision floating point adder and subtractor +// 5. DFPU_MISC Double precision floating point miscellaneous operations +// 6. DFPU_MUL Double precision floating point multiplier +// 7. DIVI_PREP Prepare data for the divider +// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer +// 9. DP_LOGIK Control logic and result path for different functions +// 10. DP_FPU Top level of long operations datapath +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. PREPDATA Prepare data for the big multiplier +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module PREPDATA ( START, MEI, DFLOAT, BWD, SRC1, SRC2, + MSD_1, MSD_2, LSD_1, LSD_2, LOAD_MSD, LOAD_LSD1, LOAD_LSD2 ); + + input [1:0] START; + input MEI,DFLOAT; + input [1:0] BWD; + input [31:0] SRC1,SRC2; + + output [52:32] MSD_1,MSD_2; + output [31:0] LSD_1,LSD_2; + output LOAD_MSD,LOAD_LSD1,LOAD_LSD2; + + reg [31:0] LSD_1,LSD_2; + + assign MSD_1 = MEI ? 21'h0 : {1'b1,SRC1[19:0]}; + assign MSD_2 = MEI ? 21'h0 : {1'b1,SRC2[19:0]}; + + always @(MEI or BWD or SRC1) + casex ({MEI,BWD}) + 3'b100 : LSD_1 = {24'h000000,SRC1[7:0]}; + 3'b101 : LSD_1 = {16'h0000,SRC1[15:0]}; + default : LSD_1 = SRC1; + endcase + + always @(MEI or BWD or SRC2) + casex ({MEI,BWD}) + 3'b100 : LSD_2 = {24'h000000,SRC2[7:0]}; + 3'b101 : LSD_2 = {16'h0000,SRC2[15:0]}; + default : LSD_2 = SRC2; + endcase + + assign LOAD_MSD = (START[0] & MEI) | (START[0] & DFLOAT); // 1. step data load at DFLOAT + assign LOAD_LSD1 = (START[0] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT + assign LOAD_LSD2 = (START[1] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. BCDADDER 4 bit BCD adder +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module BCDADDER ( A_IN, B_IN, CY_IN, SUBP, OUT, CY_OUT ); + + input [3:0] A_IN,B_IN; + input CY_IN; + input SUBP; + + output [3:0] OUT; + output CY_OUT; + + wire [4:0] result; + wire over; + + assign result = SUBP ? ({1'b0,A_IN} - {1'b0,B_IN} - {4'b0,CY_IN}) + : ({1'b0,A_IN} + {1'b0,B_IN} + {4'b0,CY_IN}); + + assign over = result[4] | (result[3] & (result[2] | result[1])); + + // if result<0 : -6 if result>9 : -10 + assign OUT = result[3:0] - (SUBP ? {1'b0,result[4],result[4],1'b0} : {over,1'b0,over,1'b0}); + assign CY_OUT = SUBP ? result[4] : over; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DFPU_BCD ( BCLK, BRESET, START, DO_BCD, BWD, SRC1, SRC2, CY_IN, SUBP, BCD_Q, CY_OUT, BCD_DONE ); + + // Byte : 3 cycles in shortest case REG-REG, Word : 4 cycles and Double : 6 cycles + input BCLK; + input BRESET; + input START; // START[1] + input DO_BCD; // BCD Opcode is valid + input [1:0] BWD; + input [31:0] SRC1,SRC2; // Source , Destination, data is stable during operation + input CY_IN; // comes from PSR + input SUBP; // SUBP = 1 : SUBP , 0 : ADDP + + output reg [31:0] BCD_Q; + output reg CY_OUT; // went to PSR if DONE is valid + output BCD_DONE; + + reg run_bcd; + reg [1:0] byte_cou; + reg [15:0] datain; + + wire [7:0] result; + wire carry,carry_lsd,carry_msd; + + // START : _/---\________________ + // byte_cou : xxxxxx 0 x 1 x 2 x 3 x + // BCD_DONE : _____/---\____________ if BWD = Byte + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) run_bcd <= 1'b0; + else + run_bcd <= (START & DO_BCD) | (run_bcd & (BWD != byte_cou)); + + always @(posedge BCLK) byte_cou <= START ? 2'd0 : byte_cou + {1'b0,run_bcd}; + + always @(*) + casex ({START,byte_cou}) + 3'b1_xx : datain = {SRC1[7:0], SRC2[7:0]}; + 3'b0_00 : datain = {SRC1[15:8], SRC2[15:8]}; + 3'b0_01 : datain = {SRC1[23:16],SRC2[23:16]}; + 3'b0_1x : datain = {SRC1[31:24],SRC2[31:24]}; + endcase + + assign carry = START ? CY_IN : CY_OUT; + + BCDADDER lsd_inst ( .A_IN(datain[3:0]), .B_IN(datain[11:8]), .CY_IN(carry), .SUBP(SUBP), + .OUT(result[3:0]), .CY_OUT(carry_lsd) ); + + BCDADDER msd_inst ( .A_IN(datain[7:4]), .B_IN(datain[15:12]), .CY_IN(carry_lsd), .SUBP(SUBP), + .OUT(result[7:4]), .CY_OUT(carry_msd) ); + + always @(posedge BCLK) CY_OUT <= carry_msd; + + always @(posedge BCLK) if (START) BCD_Q[7:0] <= result; + always @(posedge BCLK) if (byte_cou == 2'd0) BCD_Q[15:8] <= result; + always @(posedge BCLK) if (byte_cou == 2'd1) BCD_Q[23:16] <= result; + always @(posedge BCLK) if (byte_cou[1]) BCD_Q[31:24] <= result; + + assign BCD_DONE = run_bcd & (BWD == byte_cou); + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. DFPU_ADDSUB Double precision floating point adder and subtractor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//module DFPU_ADDSUB ( BCLK, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, BWD, SELECT, OUT, IOUT, CMPRES ); +// +// input BCLK; +// input [1:0] START; +// input [31:0] SRC1,SRC2; // The input data +// input [20:0] MAN1,MAN2; +// input [5:0] SRCFLAGS; // NAN, ZERO and SIGN of operands +// input [1:0] BWD; // size of integer +// input [3:0] SELECT; // upper 2 bits : R.T.F. code +// +// output [69:0] OUT; +// output [31:0] IOUT; // result of ROUNDLi/TRUNCLi/FLOORLi = R.T.F. +// output [1:0] CMPRES; +// +// reg [69:0] outreg; +// reg [31:0] IOUT; +// +// // MOViL : 2 cycles +// // ROUNDLi : 3 cycles (+TRUNC & FLOOR) +// // ADD/SUB : 4 cycles +// // CMP : 2 cycles +// +// // ++++++++++++++++++++++++++++++++++ +// // MOViL : 1. Pipeline stage : needs 3 cycles +// +// reg [31:8] movdat; +// reg [31:0] movif; +// reg sign_movif; +// +// always @(BWD or SRC1) +// casex({BWD,SRC1[15],SRC1[7]}) +// 4'b00x0 : movdat = 24'h0000_00; // Byte +// 4'b00x1 : movdat = 24'hFFFF_FF; +// 4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word +// 4'b011x : movdat = {16'hFFFF,SRC1[15:8]}; +// default : movdat = SRC1[31:8]; // Double +// endcase +// +// // This pipeline stage for better timing +// always @(posedge BCLK) movif <= movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]}; // -2^31 is kept ! +// +// always @(posedge BCLK) sign_movif <= movdat[31]; +// +// // ROUNDLi/TRUNCLi/FLOORLi : 1. pipeline stage : can Opcode-Decoder deliver direct the 64 bit operand ? From register "yes" +// +// reg ovflag,ovflag2; +// reg rovfl; +// reg minint; +// wire [11:0] rexdiff,rexo; +// wire ganzklein; // Flag for 0 +// +// assign rexdiff = 12'h41D - {1'b0,SRC1[30:20]}; // 4..0 is the right shift value : like Single FP same value space +// +// // ovflag2 at the end of rounding : Check for Overflow +// always @(posedge BCLK) rovfl <= (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint; +// +// // a large positiv difference is a very small number : +// assign ganzklein = (~rexdiff[11] & (rexdiff[10:5] != 6'b0)); // 0 is implicit via SRC1[30:20]=0 +// +// // Detection of Overflow +// assign rexo = ({1'b0,SRC1[30:20]} - {11'h1FF,~BWD[1]}); // subtract B/W = 3FF , D = 3FE +// +// always @(BWD or rexo) // 0 ist in implicitly +// casex (BWD) +// 2'b00 : ovflag = (~rexo[11] & (rexo[10:3] != 8'h0)); // Exponent 0..7 because -128.4 => -128 +// 2'b01 : ovflag = (~rexo[11] & (rexo[10:4] != 7'h0)); // Exponent 0..15 look above +// default : ovflag = (~rexo[11] & (rexo[10:5] != 6'h0)); // but Exponent only 0..30 +// endcase +// +// always @(posedge BCLK) +// if (START[1]) minint <= (SRC1 == 32'hC1E0_0000) & (SRC2 == 32'h0) & BWD[1]; // detection of -2^31 +// +// // ++++++++++++++++++++++++++++++++++++ +// // ADD/SUB : 1. Pipeline Stage : which operand ist bigger ? Exchange if neccessary +// // SUB/CMP : SRC2 - SRC1 +// +// reg ex_null,ma_null,ex_msb,ma_msb; +// reg [10:0] expo1,expo2; +// wire [11:0] exdiff,exdiff12; +// wire [20:0] madiff; +// wire switch,nan,sign,sign1,sign2; +// reg [5:0] shift1,shift2; +// +// // Pipeline register : +// reg [63:0] muxsrc2; +// reg [55:3] pipe1; // Nummbers for right shifter +// reg [5:0] shift; +// reg vorz,addflag; +// +// wire [52:0] muxsrc1; +// wire [32:0] lowdiff; +// +// assign nan = (SELECT[1:0] == 2'b11) ? SRCFLAGS[1] : (~SELECT[1] & (SRCFLAGS[3] | SRCFLAGS[1])); // used at the end +// +// assign exdiff = {1'b0,SRC2[30:20]} - {1'b0,SRC1[30:20]}; // Difference of Exponents +// assign madiff = {1'b0,SRC2[19:0]} - {1'b0,SRC1[19:0]}; // Difference of Mantissa +// assign exdiff12 = {1'b0,SRC1[30:20]} - {1'b0,SRC2[30:20]}; // Diff. Exponents exchanged +// +// always @(posedge BCLK) +// if (START[0]) +// begin +// ex_null <= (exdiff[10:0] == 11'h0); +// ma_null <= (madiff[19:0] == 20'h0); +// ex_msb <= exdiff[11]; +// ma_msb <= madiff[20]; +// shift1 <= (exdiff[10:6] != 5'h0) ? 6'h3F : exdiff[5:0]; +// shift2 <= (exdiff12[10:6] != 5'h0) ? 6'h3F : exdiff12[5:0]; +// expo1 <= SRC1[30:20]; +// expo2 <= SRC2[30:20]; +// end +// +// assign lowdiff = {1'b0,SRC2} - {1'b0,SRC1}; // LSD compare +// +// assign switch = ex_msb | (ex_null & (ma_msb | (ma_null & lowdiff[32]))); // exchange ? +// +// assign muxsrc1 = switch ? {MAN2,SRC2} : {MAN1,SRC1}; +// +// always @(posedge BCLK) // Pipeline Reg +// begin +// muxsrc2 <= switch ? {expo1,MAN1,SRC1} : {expo2,MAN2,SRC2}; // Incl. Exponent & "1" of mantissa +// pipe1 <= SELECT[1] ? (ganzklein ? 53'd0 : {1'b1,SRC1[19:0],SRC2}) : muxsrc1; // Feeding of R.T.F. +// shift <= SELECT[1] ? {1'b0,rexdiff[4:0]} : (switch ? shift2 : shift1); +// end +// +// // SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1 +// // 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0 +// // 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2 +// // (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2 +// // (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8 +// // 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1 +// // 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8 +// // (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8 +// // (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2 +// +// assign sign1 = SRCFLAGS[4]; +// assign sign2 = SRCFLAGS[5]; +// +// always @(posedge BCLK) // Pipeline Reg +// begin +// vorz <= switch ? (SELECT[0] ^ sign1) : sign2; +// addflag <= ~(SELECT[0] ^ (sign1 ^ sign2)); +// end +// +// // CMPF : 1. Pipeline Stage : first result : is stored one level higer in Reg +// +// assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // look table above +// assign CMPRES[0] = (ex_null & ma_null & (sign1 == sign2) & (lowdiff == 33'h0)) | (SRCFLAGS[2] & SRCFLAGS[0]); +// +// // ++++++++++++++++++++++++++++++++++ +// // ADD/SUB + ROUND/TRUNC : 2. Step : Barrelshifter to the right --> +// +// wire [55:0] brshifta,brshiftb,brshiftc,brshiftd,brshifte,brshiftf; +// +// // 5..33322222222221111111111 is this picture still correct ? Took over from Single FP +// // 5..2109876543210987654321098765432-10 +// // 1..VVVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 bit for rounding +// +// assign brshifta = shift[5] ? {32'h0, pipe1[55:33], (pipe1[32:3] != 30'h0)} : {pipe1,3'h0}; +// assign brshiftb = shift[4] ? {16'h0,brshifta[55:17],(brshifta[16:0] != 17'h0)} : brshifta; +// assign brshiftc = shift[3] ? { 8'h0, brshiftb[55:9], (brshiftb[8:0] != 9'h0)} : brshiftb; +// assign brshiftd = shift[2] ? { 4'h0, brshiftc[55:5], (brshiftc[4:0] != 5'h0)} : brshiftc; +// assign brshifte = shift[1] ? { 2'h0, brshiftd[55:3], (brshiftd[2:0] != 3'h0)} : brshiftd; +// assign brshiftf = shift[0] ? { 1'b0, brshifte[55:2], (brshifte[1:0] != 2'h0)} : brshifte; +// +// // ++++++++++++++++++++++++++++++++++ +// // ROUNDLi/TRUNCLi/FLOORLi : 3. Step : round to Integer +// +// reg car_ry; +// wire [1:0] inex; +// wire [30:0] compl; +// wire [31:0] iadder; +// wire restbits; +// +// assign restbits = (brshiftf[23:0] != 24'h0); +// assign inex = {brshiftf[24],restbits}; // Inexact-Flag-Data transfered to multiplexer at the end +// +// always @(SELECT or sign1 or brshiftf or restbits or inex or ganzklein) +// casex (SELECT[3:2]) +// 2'b00 : car_ry = sign1 ^ (((brshiftf[25:24] == 2'b11) & ~restbits) | (inex == 2'b11)); // ROUNDLi +// 2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers to "-infinity" round +// default : car_ry = sign1; // TRUNCLi , simple cut off +// endcase +// +// assign compl = sign1 ? ~brshiftf[55:25] : brshiftf[55:25]; +// +// assign iadder = {sign1,compl} + {31'h0,car_ry}; +// +// always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder; +// +// always @(iadder or BWD or sign1) // special overflow detection i.e. -129 to -255 at Byte +// casex (BWD) // or 127.9 -> 128 = error ! +// 2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte +// 2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word +// default : ovflag2 = 1'b0; +// endcase +// +// // ++++++++++++++++++++++++++++++++++ +// // ADD/SUB : 3. Step : Addition or Subtraction +// +// wire [67:0] result; +// wire [55:0] blshifti; +// wire [12:0] shiftl; +// wire shift_32; +// wire [65:0] add_q; +// +// // The central adder : the subtraction needs 3 Guard-Bits after LSB for correct rounding +// assign result = {1'b0,muxsrc2,3'b000} + (addflag ? {12'h0,brshiftf} : {12'hFFF,~brshiftf}) + {67'd0,~addflag}; +// +// assign blshifti = SELECT[1] ? {movif,24'h0} : result[55:0]; // Feeding of MOViL, comes from Register +// +// assign shiftl = SELECT[1] ? 13'h041E : {1'b0,result[67:56]}; // MOViL +// +// assign shift_32 = (blshifti[55:24] == 32'h0); +// +// // In case of ADD the result bypasses the barrelshifter : LSB of exponent has changed +// assign add_q = (muxsrc2[53] != result[56]) ? {result[67:3],(result[2:0] != 3'b000)} +// : {result[67:56],result[54:2],(result[1:0] != 2'b00)} ; +// +// // ++++++++++++++++++++++++++++++++++ +// // ADD/SUB : 4. Step : Barrelshifter left for SUB and MOViF : +// +// wire shift_16,shift_8,shift_4,shift_2,shift_1,zero; +// wire [1:0] lsb_bl; +// wire [55:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte,blshiftf; +// wire [12:0] expol; +// +// assign blshifta = shift_32 ? {blshifti[23:0],32'h0} : blshifti; +// assign shift_16 = (blshifta[55:40] == 16'h0); +// assign blshiftb = shift_16 ? {blshifta[39:0],16'h0} : blshifta; +// assign shift_8 = (blshiftb[55:48] == 8'h00); +// assign blshiftc = shift_8 ? {blshiftb[47:0],8'h0} : blshiftb; +// assign shift_4 = (blshiftc[55:52] == 4'h0); +// assign blshiftd = shift_4 ? {blshiftc[51:0],4'h0} : blshiftc; +// assign shift_2 = (blshiftd[55:54] == 2'b00); +// assign blshifte = shift_2 ? {blshiftd[53:0],2'b0} : blshiftd; +// assign shift_1 = ~blshifte[55]; +// assign blshiftf = shift_1 ? {blshifte[54:0],1'b0} : blshifte; +// +// // Overflow at ROUNDLi/TRUNCLi/FLOORLi is shown in overflow of exponent , SELECT[1] is then 1 +// assign expol = shiftl - {7'h00,shift_32,shift_16,shift_8,shift_4,shift_2,shift_1}; +// +// // Inexact at ROUNDLi/TRUNCLi/FLOORLi : evaluation for all one level higher +// assign lsb_bl = (SELECT == 2'b11) ? inex : {blshiftf[2],(blshiftf[1:0] != 2'b0)}; +// +// assign zero = (~SELECT[1] & SRCFLAGS[2] & SRCFLAGS[0]) +// | ((blshifti == 56'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10))); +// +// assign sign = SELECT[1] ? sign_movif : (vorz & ~zero); // sign for MOViL +// +// // 2. Pipeline register for ADD , SUB and MOViL +// always @(posedge BCLK) +// outreg <= (addflag & ~SELECT[1]) ? {nan,zero,sign,1'b0,add_q} +// : {nan,zero,sign,expol,blshiftf[54:3],lsb_bl}; +// +// // ++++++++++++++++++++++++++++++++++ +// +// assign OUT = {outreg[69:67],(rovfl ? 2'b01 : outreg[66:65]),outreg[64:0]}; +// +//endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 5. DFPU_MISC Double precision floating point miscellaneous operations +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//module DFPU_MISC ( BCLK, START, SRC1, SRC2, SRCFLAG, MIMUX, MODE, OUT ); +// +// input BCLK; +// input START; +// input [31:0] SRC1,SRC2; +// input SRCFLAG; +// input MIMUX; +// input [3:0] MODE; +// output [69:0] OUT; +// +// reg [69:0] OUT; +// reg [63:0] daten; +// +// wire [10:0] scalb_l; +// wire nan,zero,sign; +// wire [12:0] lexpo,sexpo; +// wire [69:0] scalb_res,logb_res,fl_lf; +// +// always @(posedge BCLK) if (START) daten <= {(MIMUX ? {daten[31],scalb_l,daten[19:0]}: SRC1),SRC2}; +// +// assign nan = MODE[0] ? (daten[62:55] == 8'hFF) : (daten[62:52] == 11'h7FF); +// assign zero = MODE[0] ? (daten[62:55] == 8'h00) : (daten[62:52] == 11'h000); +// assign sign = daten[63] & ~zero; +// +// assign lexpo = {5'b0,daten[62:55]} + 13'h0380; // -7F + 3FF +// +// assign sexpo = (daten[62:52] > 11'h47E) ? 13'h0FFF +// : ((daten[62:52] < 11'h381) ? 13'h0 : {2'b0,{4{daten[62]}},daten[58:52]}); +// +// assign fl_lf = MODE[0] ? {nan,zero,sign,lexpo,daten[54:32],31'h0} // MOVFL +// : {nan,zero,sign,sexpo,daten[51:29],28'h0,daten[29:28],(daten[27:0] != 28'h0)}; // MOVLF +// +// // +++++++++++++++++++++++++++ LOGBf +++++++++++++++++++++++++++++++++++ +// +// wire logb_null; +// wire [9:0] sel_data,unbiased,shift_l8,shift_l4,shift_l2; +// wire [8:0] shift_l; +// wire posi_8,posi_4,posi_2,posi_1; +// wire [4:0] calc_exp; +// wire [6:0] logb_exp; +// +// assign logb_null = MODE[1] ? (daten[62:55] == 8'h7F) : (daten[62:52] == 11'h3FF); +// +// assign sel_data = MODE[1] ? {{3{~daten[62]}},daten[61:55]} : daten[61:52]; +// assign unbiased = daten[62] ? (sel_data + 10'h001) : ~sel_data; +// +// // detection of leading "1" +// assign posi_8 = (unbiased[9:2] == 8'h00); +// assign shift_l8 = posi_8 ? {unbiased[1:0],8'h00} : unbiased; +// assign posi_4 = (shift_l8[9:6] == 4'h0); +// assign shift_l4 = posi_4 ? {shift_l8[5:0],4'h0} : shift_l8; +// assign posi_2 = (shift_l4[9:8] == 2'b00); +// assign shift_l2 = posi_2 ? {shift_l4[7:0],2'b0} : shift_l4; +// assign posi_1 = ~shift_l2[9]; +// assign shift_l = posi_1 ? {shift_l2[7:0],1'b0} : shift_l2[8:0]; // top bit is hidden "1" +// +// assign calc_exp = 5'h08 - {1'b0,posi_8,posi_4,posi_2,posi_1}; // Minimum is "F" = for exponent +/-1 <=> 2^0 +// +// // exponent is set one level higher for F and L +// assign logb_exp = MODE[1] ? {{4{~calc_exp[4]}},{3{calc_exp[4]}}} : {~calc_exp[4],{6{calc_exp[4]}}}; +// +// assign logb_res = logb_null ? {70'h10_0000_0000_0000_0000} : {2'b00,~daten[62],2'b00,logb_exp,calc_exp[3:0],shift_l,45'h0}; +// +// // ++++++++++++++++++++++++ SCALBf ++++++++++++++++++++++++++++++++++ +// +// wire [7:0] scalb_f; +// +// assign scalb_f = SRCFLAG ? 8'h00 : (daten[39:32] + daten[30:23]); +// assign scalb_l = SRCFLAG ? 11'h000 : (daten[42:32] + daten[30:20]); +// +// assign scalb_res = MODE[1] ? // no rounding of Single Data +// {2'b00,daten[31],5'b0,scalb_f,daten[22:0],daten[28:1],3'b000} +// : {2'b00,daten[63],2'b0,daten[62:0],2'b00}; +// +// // ++++++++++++++++++++++++ Output ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// always @(posedge BCLK) OUT <= MODE[3] ? (MODE[2] ? logb_res : scalb_res) : fl_lf ; // LOGB/SCALB : MOVLF/MOVFL +// +//endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 6. DFPU_MUL Double precision floating point multiplier +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//module DFPU_MUL ( BCLK, SRC1, SRC2, START, MRESULT, SRCFLAGS, OUT ); +// +// input BCLK; +// input [31:0] SRC1,SRC2; +// input START; // that is START[0] +// input [105:0] MRESULT; +// input [5:0] SRCFLAGS; // NAN and ZERO flags +// output [69:0] OUT; // The result +// +// reg [69:0] OUT; +// reg [12:0] exponent; +// wire orlow; +// wire [12:0] expoh,expol; +// wire [1:0] restlow,resthigh; +// wire zero,nan,sign; +// +// assign zero = SRCFLAGS[2] | SRCFLAGS[0]; // one is NULL -> NULL is the result +// assign nan = SRCFLAGS[3] | SRCFLAGS[1]; // one is NAN -> error +// assign sign = (SRCFLAGS[5] ^ SRCFLAGS[4]) & ~zero; +// +// assign orlow = (MRESULT[50:0] != 51'b0); +// +// assign restlow = {MRESULT[51],orlow}; +// assign resthigh = {MRESULT[52],(MRESULT[51] | orlow)}; +// +// always @(posedge BCLK) if (START) exponent <= {2'b00,SRC1[30:20]} + {2'b00,SRC2[30:20]}; +// +// assign expoh = exponent - 13'h03FE; +// assign expol = exponent - 13'h03FF; // for MSB if MRESULT=0 +// +// always @(posedge BCLK) +// OUT <= MRESULT[105] ? {nan,zero,sign,expoh,MRESULT[104:53],resthigh} // 52 Bit Mantissa +// : {nan,zero,sign,expol,MRESULT[103:52],restlow}; +// +//endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 7. DIVI_PREP Prepare data for the divider +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DIVI_PREP (SRC, BWD, NOT_DEI, EXTDATA, DOUT, MSB, NULL, MINUS); + + input [31:0] SRC; + input [1:0] BWD; + input NOT_DEI; + input EXTDATA; + + output [31:0] DOUT; + output [4:0] MSB; + output NULL; + output MINUS; + + reg [31:0] double; + + wire [15:0] test_16; + wire [7:0] test_8; + wire [3:0] test_4; + wire [1:0] test_2; + wire bit_4,bit_3,bit_2,bit_1,bit_0; + wire [1:0] modus; + + assign modus = (NOT_DEI | EXTDATA) ? BWD : {(BWD[1] | BWD[0]),1'b1}; + + always @(modus or SRC or NOT_DEI) + casex (modus) + 2'b00 : double = {{24{SRC[7] & NOT_DEI}},SRC[7:0]}; + 2'b01 : double = {{16{SRC[15] & NOT_DEI}},SRC[15:0]}; + 2'b1x : double = SRC; + endcase + + assign MINUS = double[31] & NOT_DEI; + + assign DOUT = ({32{MINUS}} ^ double) + {31'h0,MINUS}; // assign DOUT = MINUS ? (32'd0 - double) : double; + + // now find most significant set bit : FFS + + assign bit_4 = (DOUT[31:16] != 16'h0); + assign test_16 = bit_4 ? DOUT[31:16] : DOUT[15:0]; + assign bit_3 = (test_16[15:8] != 8'h0); + assign test_8 = bit_3 ? test_16[15:8] : test_16[7:0]; + assign bit_2 = (test_8[7:4] != 4'h0); + assign test_4 = bit_2 ? test_8[7:4] : test_8[3:0]; + assign bit_1 = (test_4[3:2] != 2'b0); + assign test_2 = bit_1 ? test_4[3:2] : test_4[1:0]; + assign bit_0 = test_2[1]; + assign NULL = (test_2 == 2'b00); + + assign MSB = {bit_4,bit_3,bit_2,bit_1,bit_0}; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DFPU_DIV ( BCLK, BRST, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, FL, BWD, OPCODE, OUT, DONE, DIVI_OUT, DVZ_TRAP, DEI_OVF ); + + // This version needs for Double 28+1 cycles if MAN1 0 at DEI + + // ++++++++++++++ Floating Point & calculation path ++++++++ + reg [69:0] OUT; + reg [32:0] save1; + reg runflag; + reg [55:0] dreimal; + reg [56:0] divreg,divsr; + reg [31:0] divreg_ext; + reg [12:0] exponent; + + wire load_src1,load_src2; + wire [56:0] sub1,sub2,sub3; + wire [32:0] src_1; + wire [20:0] man_1; + wire [12:0] expoh,expol,offset; + wire restlsb,restlow,resthigh; + wire zero,nan,sign,ende; + wire orlow_s,orlow_d; + wire short; + + // +++++++++++++++++++++++++++ Integer Division, DEI +++++++++++++++++++++++++++ + + assign not_dei = OPCODE[2]; // 0 = DEI + always @(posedge BCLK) if (START[3]) extdata <= ~START[1]; // during START[0] for SRC1 not valid + + always @(posedge BCLK or negedge BRST) + if (!BRST) run_divi <= 1'b0; + else + run_divi <= (START[3] & ~ist_null) | (~divi_pipe4 & run_divi); // Abort at DVZ Trap + + always @(posedge BCLK) divi_pipe1 <= START[3] & ~ist_null; // no start if SRC1 = 0 : DVZ Trap + always @(posedge BCLK) dei_pipe <= divi_pipe1 & extdata; + always @(posedge BCLK) divi_pipe2 <= extdata ? dei_pipe : divi_pipe1; + + always @(posedge BCLK) src2_reg <= SRC2; + + always @(posedge BCLK) sel_in <= START[3] | divi_pipe1; // two times data for DEI + assign i_in = sel_in ? src2_reg : SRC1; + + DIVI_PREP prep_inst ( .SRC(i_in), .BWD(BWD), .NOT_DEI(not_dei), .EXTDATA(extdata | START[0]), + .DOUT(i_out[31:0]), .MSB(i_out[36:32]), .NULL(ist_null), .MINUS(i_out[37]) ); + + always @(posedge BCLK) dvz_pipe <= START[3] & ist_null; // Pulse 1 cycle long + always @(posedge BCLK) DVZ_TRAP <= dvz_pipe; // one cycle later if DEI with extdata + + always @(posedge BCLK) + if (START[3]) + begin + neg_src1 <= i_out[37]; + msb_src1 <= i_out[36:32]; + end + + always @(posedge BCLK) + if (divi_pipe1) + begin + nul_src2 <= ist_null; + neg_src2 <= i_out[37]; + end + + always @(posedge BCLK) ivalue <= i_out[31:0]; + + // The following is only for DEI : + always @(posedge BCLK) pipe_reg <= {32{extdata}} & ivalue; // Register must be 0 if not used + + assign valdata = extdata & ~ist_null; + always @(BWD or valdata) + casex (BWD) + 2'b00 : addoff = { 1'b0, 1'b0,valdata}; + 2'b01 : addoff = { 1'b0,valdata, 1'b0}; + default : addoff = {valdata, 1'b0, 1'b0}; + endcase + + always @(posedge BCLK) next_msb2 <= extdata & ist_null & divi_pipe1; // Special case at DEI : MSD = 0 + + always @(posedge BCLK) + if (divi_pipe1) msb_src2 <= {addoff[2],(addoff[1:0] | i_out[36:35]),i_out[34:32]}; + else + if (next_msb2) msb_src2 <= {1'b0,i_out[36:32]}; + + // Shifter for Source2 + + assign diff_msb = {1'b0,msb_src2} - {2'b0,msb_src1}; + + // negativ shift limited to 0 : Source2=0 calculated without special handling, result always 0 + assign shift_r = diff_msb[6] ? 5'd0 : diff_msb[5:1]; // LSB does not count + + always @(BWD or extdata or ivalue or pipe_reg) + casex ({BWD,extdata}) + 3'b0x0 : din_mux = {31'b0,ivalue}; // the normal case for all except DEI + 3'b001 : din_mux = {23'b0,pipe_reg,ivalue[7:0]}; + 3'b011 : din_mux = {15'b0,pipe_reg,ivalue[15:0]}; + default : din_mux = {pipe_reg[30:0],ivalue}; // 63 Bit wide + endcase + + assign shift_2 = shift_r[1] ? din_mux : {din_mux[60:0], 2'b0}; + assign shift_4 = shift_r[2] ? shift_2 : {shift_2[58:0], 4'b0}; + assign shift_8 = shift_r[3] ? shift_4 : {shift_4[54:0], 8'b0}; + assign shift_16 = shift_r[4] ? shift_8 : {shift_8[46:0],16'b0}; // Result is 63 Bit wide + + // 65 Bit result because of DEI + assign shift_32 = shift_r[5] ? {1'b0,pipe_reg,ivalue} : {shift_16,2'b00}; // special case DEI : 32 times shift + + always @(posedge BCLK or negedge BRST) // Flag for rounding, only if DEST <>0 + if (!BRST) divi_pipe3 <= 1'b0; + else + divi_pipe3 <= divi_pipe2 | (divi_pipe3 & ~stop_divi); + + always @(posedge BCLK) + if (divi_pipe2) divi_counter <= shift_r; + else divi_counter <= divi_counter - {4'b000,~stop_divi}; // should stop at 0 + + assign stop_divi = (divi_counter == 5'h0); // caclulation ready + + always @(posedge BCLK) divi_pipe4 <= divi_pipe3 & stop_divi; + + assign neg_flag = neg_src1 ^ neg_src2; + assign rest_null = (divreg[33:2] == 32'h0); + + always @(posedge BCLK) sub_case <= neg_flag & ~nul_src2; // little help for MODi opcode + + // Result preparation : + // DEST SRC QUO REM / DIV MOD + // +33 +13 : 2 7 / 2 7 + // +33 -13 : -2 7 / -3 -6 + // -33 +13 : -2 -7 / -3 6 + // -33 -13 : 2 -7 / 2 -7 + always @(*) + case (OPCODE[1:0]) + 2'b00 : divi_result = {neg_flag,divsr[31:0]}; // QUO + 2'b01 : divi_result = {neg_src2,divreg[33:2]}; // REM + 2'b10 : divi_result = {neg_src1,((sub_case & ~rest_null) ? (save1[31:0] - divreg[33:2]) : divreg[33:2])}; // MOD + 2'b11 : divi_result = {neg_flag,divsr[31:0]}; // DIV + endcase + + always @(posedge BCLK) negativ <= divi_result[32]; + + assign plus_1 = (OPCODE[1:0] == 2'b11) ? (negativ & rest_null) : negativ; // Special case Rest=0 at DIV + + always @(posedge BCLK) + if (divi_pipe4) DIVI_OUT[63:32] <= not_dei ? (({32{negativ}} ^ divi_result[31:0]) + {31'd0,plus_1}) : dei_result; + + always @(posedge BCLK) if (divi_pipe4) DIVI_OUT[31:0] <= divreg[33:2]; + + always @(extdata or BWD or divsr or divreg) + casex ({extdata,BWD}) + 3'b000 : dei_result = {16'hxxxx,divsr[7:0],divreg[9:2]}; + 3'b001 : dei_result = {divsr[15:0],divreg[17:2]}; + default : dei_result = divsr[31:0]; + endcase + + // +++++++++++++++++++++++++++ Calculation path for Division ++++++++++++++++++++++++++++ + + always @(posedge BCLK or negedge BRST) + if (!BRST) runflag <= 1'b0; + else + runflag <= START[2] | (~ende & runflag); + + always @(posedge BCLK) DONE <= (ende & runflag) | divi_pipe4; + + assign man_1 = (FL | run_divi) ? 21'h0 : MAN1; + assign src_1 = run_divi ? {1'b0,ivalue} : ( FL ? {10'h001,SRC1[22:0]} : {SRC1,1'b0}); + + assign load_src1 = START[2] | divi_pipe1; + + // *2 + *1 + always @(posedge BCLK) if (load_src1) dreimal <= {1'b0,man_1,src_1,1'b0} + {2'b00,man_1,src_1}; // 54 Bit Reg + + always @(posedge BCLK) if (load_src1) save1 <= src_1; + + assign sub1 = divreg - {3'b000, man_1,save1 }; + assign sub2 = divreg - {2'b00 ,man_1,save1,1'b0}; + assign sub3 = divreg - {1'b0, dreimal }; + + assign load_src2 = START[2] | divi_pipe2; + + always @(posedge BCLK) + if (load_src2) divreg <= divi_pipe2 ? {23'h0,shift_32[64:32]} : ( FL ? {34'h0_0000_0001,SRC2[22:0]} : {3'b0,MAN2,SRC2,1'b0}); + else + begin + casex ({sub3[56],sub2[56],sub1[56]}) + 3'b0xx : divreg <= {sub3[54:0],divreg_ext[31:30]}; + 3'b10x : divreg <= {sub2[54:0],divreg_ext[31:30]}; + 3'b110 : divreg <= {sub1[54:0],divreg_ext[31:30]}; + default : divreg <= {divreg[54:0],divreg_ext[31:30]}; + endcase + end + + always @(posedge BCLK) // Extension Register for Integer Division + if (load_src2) divreg_ext <= divi_pipe2 ? shift_32[31:0] : 32'd0; + else + divreg_ext <= {divreg_ext[29:0],2'b0}; + + always @(posedge BCLK) + if (load_src2) divsr <= 57'h0; + else + begin + casex ({sub3[56],sub2[56],sub1[56]}) + 3'b0xx : divsr <= {divsr[54:0],2'b11}; + 3'b10x : divsr <= {divsr[54:0],2'b10}; + 3'b110 : divsr <= {divsr[54:0],2'b01}; + default : divsr <= {divsr[54:0],2'b00}; + endcase + end + + // Overflow Detection for DEI : serial calculation + always @(posedge BCLK) + if (load_src2) DEI_OVF[0] <= 1'b0; + else DEI_OVF[0] <= DEI_OVF[0] | (BWD[1] ? |divsr[33:32] : (BWD[0] ? |divsr[17:16] : |divsr[9:8])); + + always @(posedge BCLK) DEI_OVF[1] <= divi_pipe4; // Timing pulse for OVF inclusiv for DIV and QUO + + assign short = (SRCFLAGS[3:0] != 4'h0) & runflag; + + assign ende = ((FL ? (divsr[26] | divsr[25]) : (divsr[56] | divsr[55])) & runflag) | short; + + assign sign = (SRCFLAGS[4] ^ SRCFLAGS[5]) & ~zero; + assign zero = SRCFLAGS[2] & ~SRCFLAGS[0]; // SRC2 = NULL -> NULL as result + assign nan = SRCFLAGS[3] | SRCFLAGS[1] | (SRCFLAGS[2] & SRCFLAGS[0]); + // one of both NAN or both 0 -> invalid Operation + + assign orlow_d = (divreg[56:27] != 29'b0) & ~zero & ~FL; // is there Rest ? [1:0] are always 0. + assign orlow_s = (divreg[26:2] != 25'b0) & ~zero; + + assign restlsb = divsr[0] | orlow_s; + assign restlow = (divsr[1:0] != 2'b00) | orlow_s | orlow_d; + assign resthigh = divsr[2] | restlow; + + always @(posedge BCLK) if (START[0]) exponent <= FL ? ({5'b00,SRC2[30:23]} - {5'b00,SRC1[30:23]}) + : ({2'b00,SRC2[30:20]} - {2'b00,SRC1[30:20]}); + assign offset = FL ? 13'h007E : 13'h03FE; + assign expoh = exponent + {offset[12:1],1'b1}; // Double = 3FF/3FE Single = 7F/7E + assign expol = exponent + offset; // in case of normalizing + + always @(posedge BCLK) + if (ende && runflag) + casex ({FL,divsr[26],divsr[56]}) + 3'b11x : OUT <= {nan,zero,sign,expoh[9:8],expoh[7],expoh[7],expoh[7],expoh[7:0],divsr[25:3],28'b0,divsr[3:2],restlow}; + 3'b10x : OUT <= {nan,zero,sign,expol[9:8],expol[7],expol[7],expol[7],expol[7:0],divsr[24:2],28'b0,divsr[2:1],restlsb}; + 3'b0x1 : OUT <= {nan,zero,sign,expoh,divsr[55:3],resthigh}; + 3'b0x0 : OUT <= {nan,zero,sign,expol,divsr[54:2],restlow}; + endcase + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 9. DP_LOGIK Control logic and result path for different functions +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DP_LOGIK ( BCLK, BRESET, OPCODE, SRC1, SRC2, FSR, START, MRESULT, BWD, FL, MAN1, MAN2, WR_REG, CY_IN, + COP_DONE, COP_OP, COP_IN, + DOUT, TT_DP, DP_CMP, OVF_BCD, MEI, DFLOAT, DONE, UP_DP, CLR_LSB, WREN_L, LD_OUT_L, DVZ_TRAP, COP_GO ); + +// Definition of output word OUT of sub-moduls : the hidden-bit of the mantissa is already gone +// +// N Z S Exponent Mantissa Round +// A E I Double : 13 Bit 52 Bit 2 Bit +// N R G Single : 10 Bit 23 Bit 2 Bit +// O N -mmmm.mmmm.mmmm.mmmm.mmmm.mmm-.-- -m. +// -F-F-F-E.EEEE.EEEE.EEEE-MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.RR +// +// 6 6 6 6 6666 6655 5555 5555 4444 4444 4433 3333 3333 2222 2222 2211 1111 1111 0000 0000 00 +// 9 8 7 6 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 10 +// +// Single FP delivers the exponent in a way, that it is identical for rounding : +// +// Exponent 61 - 54 => kept +// Bits 64 - 62 are filled with bit 61 , carry should come through +// Exponent 62 => Bit 65 , Overflow +// Exponent 63 => Bit 66 , Underflow + + input BCLK,BRESET; + input [7:0] OPCODE; + input [31:0] SRC1,SRC2; // the input data + input [20:0] MAN1,MAN2; // the MSB of mantissa + input [8:3] FSR; // Floating Point Status Register + input [1:0] START; + input [105:0] MRESULT; // Result of multiplier + input [1:0] BWD; // Size of integer + input FL; + input WR_REG; // from DECODER + input CY_IN; + input COP_DONE; // Coprozessor Interface + input [23:0] COP_OP; + input [63:0] COP_IN; + + output [63:0] DOUT; + output [4:0] TT_DP; // Trap-Info to FSR + output [2:0] DP_CMP; // CMPL result + output [3:0] OVF_BCD; // Integer Division Overflow + BCD Carry update + output MEI,DFLOAT; + output DONE,UP_DP; + output CLR_LSB,WREN_L,LD_OUT_L; + output DVZ_TRAP; + output reg COP_GO; + + reg [63:0] DOUT; + reg CLR_LSB; + reg [2:0] DP_CMP; + reg [5:0] preflags; + reg [5:0] srcflags; +// reg [69:0] fpout; + wire [69:0] fpout; + reg [2:0] tt; + reg [6:0] select; + reg [4:0] wctrl; + reg [2:1] sequ; + reg misc_op; + reg misc_mux; + reg car_ry; + reg wr_part2; + reg up_flag; + reg ovf_div; + + wire zexp2,zman2,zexp1,zman1,znan1; + wire make_i; + wire scalbl,go_misc; + wire op_cmp; + wire [69:0] mulout,addout,divout,miscout; + wire go_divf,go_divi,divi_ops,div_done; + wire bcd_ops,man_ops; + wire [31:0] i_out; + wire [63:0] divi_out; + wire [66:2] rund,cy_val; // Indexnumber like in xxxout + wire div_zero,overflow,underflow,inexact; + wire [1:0] cmpres; + wire [63:0] fp_out,fp_res; + wire wr_part1; + wire done_i; + wire [31:0] bcd_q; + wire bcd_done; + wire bcd_carry; + wire [1:0] dei_ovf; + wire quo_div; + wire copop; + wire copwr; + + // Control of datapath : together with START the Double Unit becomes activ + + always @(OPCODE or FL) + casex (OPCODE) + 8'b1001_000x : select = 7'b00_01010; // 0 1 0 : MOViL + 8'b1001_010x : select = 7'b10_11000; // MOVLF + 8'b1001_011x : select = 7'b01_11000; // MOVFL + 8'b1001_100x : select = 7'b10_01011; // 0 1 1 : ROUNDLi + 8'b1001_101x : select = 7'b10_01011; // 0 1 1 : TRUNCLi + 8'b1001_111x : select = 7'b10_01011; // 0 1 1 : FLOORLi + 8'b1011_0000 : select = 7'bxx_01000; // 0 0 0 : ADDL + 8'b1011_0010 : select = 7'bxx_01001; // 0 0 1 : CMPL + 8'b1011_0100 : select = 7'bxx_01001; // 0 0 1 : SUBL + 8'b1011_1000 : select = 7'b11_01100; // 1 0 1 : DIVf , Default Float for srcflags + 8'b1011_1100 : select = 7'bxx_01100; // 1 0 0 : MULL + 8'b1011_0110 : select = 7'b11_11000; // SCALBf , Default Float for srcflags + 8'b1011_0111 : select = {~FL,FL,5'b11000}; // LOGBf + default : select = 7'b0; + endcase + + assign MEI = (OPCODE == 8'h79); + assign divi_ops = (OPCODE[7:2] == 6'b0111_11) | (OPCODE == 8'h7B); // QUO/REM/MOD/DIV & DEI + assign go_divf = (OPCODE == 8'hB8) & START[1]; // because of runflag in DIV Unit + assign go_divi = divi_ops & (OPCODE[2] ? START[1] : START[0]); // DEI starts with START[0] + assign bcd_ops = (OPCODE == 8'h6F) | (OPCODE == 8'h6B); // ADDP , SUBP + + assign man_ops = (OPCODE == 8'hB1) | (OPCODE == 8'hB5) | (OPCODE == 8'hB9) | (OPCODE == 8'hBD); // MOVf,NEGf,XXXf,ABSf + + assign DFLOAT = (select[3] | copop) & ~FL; // all Double Floating Point Operations for PREPDATA + assign make_i = (select[2:0] == 3'b011) | divi_ops | bcd_ops; // ROUND/TRUNC/FLOOR for output multiplexer + assign op_cmp = (OPCODE == 8'hB2) & ~FL; + always @(posedge BCLK) misc_op <= select[4]; // for OUT-Multiplexer + + assign copop = (OPCODE == 8'hDD); + assign copwr = (COP_OP[18:17] == 2'd0) & (COP_OP[13:11] == 3'b111) & (COP_OP[7:5] == 3'b001); // Custom Convert + + // very special solution for SCALBL + assign scalbl = START[0] & ~FL & (OPCODE == 8'hB6); + assign go_misc = START[1] | scalbl; + always @(posedge BCLK) misc_mux <= scalbl; // switches at START[1] the input multiplexer + + // SRCFLAGS : special handling for operands is done locally + + assign zexp2 = (SRC2[30:20] == 11'd0); + assign zman2 = (SRC2[19:0] == 20'd0); + assign zexp1 = (SRC1[30:20] == 11'd0); + assign zman1 = (SRC1[19:0] == 20'd0); + assign znan1 = (SRC1[30:20] == 11'h7FF); + + always @(posedge BCLK) + if (START[0]) + begin + srcflags[5] <= SRC2[31]; + srcflags[4] <= SRC1[31]; + preflags <= {(SRC2[30:20] == 11'h7FF),zexp2,zman2,znan1,zexp1,zman1}; + end + + // case Definition : 00 : 0 , if START[i]=0 then there are always 2 long operands + // 01 : 1 Float Operand SCR1 + // 10 : 1 Long Operand SRC1+SRC2 + // 11 : 2 Float Operands SRC1 , SRC2 + + always @(posedge BCLK) // NaN + if (START[1]) + casex ({START[0],select[6:5]}) + 3'b0xx : srcflags[3] <= preflags[5] | (preflags[4] & (~preflags[3] | SRC2[31] | ~zexp2 | ~zman2)); + 3'b111 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd0) | ~zman2)); // F:SRC2 = NaN + default : srcflags[3] <= 1'b0; + endcase + + always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN ! + if (START[0]) + casex ({START[1],select[6:5]}) + 3'b0xx : srcflags[2] <= zexp2; // L:(SRC1,SRC2) = Zero , SRC1 = MSB + 3'b111 : srcflags[2] <= (SRC2[30:23] == 8'd0); // F:SRC2 = Zero + default : srcflags[2] <= 1'b0; + endcase + + always @(posedge BCLK) // NaN + if (START[1]) + casex ({START[0],select[6:5]}) + 3'b0xx : srcflags[1] <= preflags[2] | (preflags[1] & (~preflags[0] | SRC1[31] | ~zexp1 | ~zman1)); + 3'b1x1 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd0) | ~zman1)); // F:SRC1 = NaN + 3'b110 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SRC2) = NaN , SRC1 = MSB + default : srcflags[1] <= 1'b0; + endcase + + always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN ! + if (START[0]) + casex ({START[1],select[6:5]}) + 3'b0xx : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB + 3'b1x1 : srcflags[0] <= (SRC1[30:23] == 8'd0); // F:SRC1 = Zero + 3'b110 : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB + default : srcflags[0] <= 1'b0; + endcase + + // The Sub-moduls : + +// DFPU_ADDSUB as_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2), +// .MAN1({~srcflags[0],MAN1[19:0]}), .MAN2({~srcflags[2],MAN2[19:0]}), +// .SRCFLAGS(srcflags), .BWD(BWD), .SELECT({OPCODE[2:1],select[1:0]}), +// .OUT(addout), .IOUT(i_out), .CMPRES(cmpres) ); + + assign addout = 70'b0; + assign i_out = 32'b0; + assign cmpres = 2'b0; + +// DFPU_MUL mul_inst ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .START(START[0]), .MRESULT(MRESULT), +// .OUT(mulout), .SRCFLAGS(srcflags) ); + + assign mulout = 70'b0; + + + DFPU_DIV div_inst ( .BCLK(BCLK), .BRST(BRESET), .START({go_divi,go_divf,START}), .SRC1(SRC1), .SRC2(SRC2), + .MAN1(MAN1), .MAN2(MAN2), .SRCFLAGS(srcflags), .FL(FL), .OUT(divout), .DONE(div_done), + .BWD(BWD), .OPCODE(OPCODE[2:0]), .DIVI_OUT(divi_out), .DVZ_TRAP(DVZ_TRAP), .DEI_OVF(dei_ovf) ); + +// DFPU_MISC misc_inst ( .BCLK(BCLK), .START(go_misc), .SRC1(SRC1), .SRC2(SRC2), .SRCFLAG(srcflags[2]), +// .MIMUX(misc_mux), .MODE({OPCODE[5],OPCODE[0],FL,OPCODE[1]}), .OUT(miscout) ); + + assign miscout = 70'b0; + + DFPU_BCD bcd_inst ( .BCLK(BCLK), .BRESET(BRESET), .START(START[1]), .DO_BCD(bcd_ops), .BWD(BWD), .SRC1(SRC1), .SRC2(SRC2), + .CY_IN(CY_IN), .SUBP(~OPCODE[2]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) ); + + // FP - path : selection of result and rounding : + +// always @(misc_op or OPCODE or mulout or addout or divout or miscout) +// casex ({misc_op,OPCODE[5],OPCODE[3:2]}) //OPCODE[5] only for Flags i.e. NAN +// 4'b1xxx : fpout = miscout; // for MOVLF,MOVFL,SCALB & LOGB +// 4'b0110 : fpout = divout; +// 4'b0111 : fpout = mulout; +// default : fpout = addout; +// endcase + assign fpout = 70'd0; + + + always @(FSR or fpout) // Calculation of Carry according to rounding mode, fpout[67] = sign bit + casex (FSR[8:7]) + 2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest + 2'b10 : car_ry = ~fpout[67] & (fpout[1:0] != 2'b00); // round to positiv infinity + 2'b11 : car_ry = fpout[67] & (fpout[1:0] != 2'b00); // round to negativ infinity + default : car_ry = 1'b0; // round to zero + endcase + + assign cy_val = {35'h0,(FL & car_ry),28'h0,(~FL & car_ry)}; + + assign rund = {fpout[66:2]} + cy_val; + + // Detection of Div-by-0, Overflow, Underflow and Inexact : Epxonent from [66:54] = 13 Bits + assign div_zero = (srcflags[3:0] == 4'h1) & (OPCODE == 8'hB8); // true FPU Divide by Zero + assign overflow = ~rund[66] & (rund[65] | (rund[64:54] == 11'h7FF)); + assign underflow = (rund[66] | (rund[65:54] == 12'h0)) & ~fpout[68]; // Zero-Flag + assign inexact = (fpout[1:0] != 2'b00); + + always @(fpout or op_cmp or div_zero or overflow or underflow or inexact or FSR) + casex ({fpout[69],op_cmp,div_zero,overflow,FSR[3],underflow,FSR[5],inexact}) // [69] = NAN + 8'b1xxxxxxx : tt = 3'b101; // Invalid operation + 8'b001xxxxx : tt = 3'b011; // Divide by Zero + 8'b0001xxxx : tt = 3'b010; // Overflow + 8'b000011xx : tt = 3'b001; // Underflow + 8'b00000011 : tt = 3'b110; // Inexact Result + default : tt = 3'b000; // no error + endcase + + assign TT_DP = man_ops ? 5'd0 : {(inexact & ~op_cmp),(underflow & ~op_cmp),tt}; // at ABSf/NEGf no error : different to NS32381 ! + + assign fp_res = FL ? {fpout[67],rund[61:31],rund[33:2]} + : {fpout[67],rund[64:2]}; // lower 32 bits identical + + // Underflow special case and get ZERO + assign fp_out = (underflow | fpout[68]) ? 64'h0 : fp_res; + + // 63..32 goes to memory if Word or Byte ! Also in ODD Register , 31..0 goes in EVEN Register + // DEI comes without WR_REG information + always @(make_i or copop or MEI or BWD or WR_REG or MRESULT or COP_IN or i_out or fp_out or divi_ops or divi_out or bcd_ops or bcd_q) + casex ({make_i,copop,MEI,BWD}) + 5'b00100 : DOUT = {MRESULT[31:8], (WR_REG ? MRESULT[15:8] : MRESULT[7:0]), MRESULT[31:0]}; // LSD always the same + 5'b00101 : DOUT = {MRESULT[31:16],(WR_REG ? MRESULT[31:16] : MRESULT[15:0]),MRESULT[31:0]}; + 5'b0011x : DOUT = MRESULT[63:0]; + 5'b01xxx : DOUT = COP_IN; // true alignment in Coprocessor + 5'b1xxxx : DOUT = divi_ops ? divi_out : {(bcd_ops ? bcd_q : i_out),fp_out[31:0]}; // MSD is written first + default : DOUT = fp_out; + endcase + + always @(posedge BCLK) DP_CMP <= {(srcflags[3] | srcflags[1]),cmpres}; // Only valid if not NaN + + // Pipeline Control + Registerfile write control + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) sequ <= 2'b00; + else + sequ <= {(sequ[1] & ~DONE),START[1]}; + + always @(FL or OPCODE or copwr) + casex ({FL,OPCODE}) // WRITE Control : [2] = clr_lsb, [1] = wr_part2, [0] = wr_part1 + 9'bx_1001_000x : wctrl = 5'b01_111; // MOViL + 9'bx_1001_010x : wctrl = 5'b00_010; // MOVLF + 9'bx_1001_011x : wctrl = 5'b01_111; // MOVFL + 9'bx_1001_100x : wctrl = 5'b00_010; // ROUNDLi - DONE is one cycle earlier for this opcodes + 9'bx_1001_101x : wctrl = 5'b00_010; // TRUNCLi + 9'bx_1001_111x : wctrl = 5'b00_010; // FLOORLi + 9'bx_1011_0000 : wctrl = 5'b01_111; // ADDL + 9'bx_1011_0010 : wctrl = 5'b00_000; // CMPL - via LD one cycle later in PSR + 9'bx_1011_0100 : wctrl = 5'b01_111; // SUBL + 9'b1_1011_1000 : wctrl = 5'b10_001; // DIVF - measured 18 cycles Reg-Reg + 9'b0_1011_1000 : wctrl = 5'b10_111; // DIVL - measured 34 cycles Reg-Reg + 9'bx_1011_1100 : wctrl = 5'b01_111; // MULL + 9'bx_0110_1x11 : wctrl = 5'b10_001; // ADDP,SUBP + 9'bx_0111_1001 : wctrl = 5'b00_111; // MEIi + 9'bx_0111_1011 : wctrl = 5'b10_111; // DEIi + 9'bx_0111_11xx : wctrl = 5'b10_001; // QUOi,REMi,MODi,DIVi + 9'b1_1011_011x : wctrl = 5'b00_010; // SCALBF/LOGBF + 9'b0_1011_011x : wctrl = 5'b01_111; // SCALBL/LOGBL + 9'bx_1101_1101 : wctrl = {4'b10_00,copwr}; // execute coprocessor opcode + default : wctrl = 5'b0; + endcase + + assign done_i = wctrl[4] ? (div_done | bcd_done | COP_DONE) : ( (wctrl[3] | ~WR_REG) ? sequ[2] : sequ[1] ); + assign DONE = ~START[1] & done_i; // DONE is valid for all opcodes + + assign wr_part1 = DONE & WR_REG & wctrl[0]; + + always @(posedge BCLK) CLR_LSB <= DONE & WR_REG & wctrl[2]; + always @(posedge BCLK) wr_part2 <= DONE & WR_REG & wctrl[1]; + + assign WREN_L = wr_part1 | wr_part2; + assign LD_OUT_L = DONE & ~WR_REG; // meaning is "Load Out-Reg from Long-Path" + + always @(posedge BCLK) up_flag <= DONE & ~wctrl[0]; // DONE one cycle later + assign UP_DP = (select[3] & (wctrl[0] ? DONE : up_flag)) | man_ops; // Update FSR Trap etc. : all FPU opcodes of DP_FPU + + // Overflow Trap for Division : DEI, QUO, DIV + assign quo_div = (OPCODE == 8'h7C) | (OPCODE == 8'h7F); + always @(*) + casex ({OPCODE[2],BWD}) + 3'b100 : ovf_div = (divi_out[39] & SRC1[7] & SRC2[7] ) & quo_div; + 3'b101 : ovf_div = (divi_out[47] & SRC1[15] & SRC2[15]) & quo_div; + 3'b11x : ovf_div = (divi_out[63] & SRC1[31] & SRC2[31]) & quo_div; + default : ovf_div = dei_ovf[0] & (OPCODE == 8'h7B); // DEI + endcase + + assign OVF_BCD = {dei_ovf[1],ovf_div,bcd_done,bcd_carry}; // to I_PFAD + + always @(posedge BCLK) COP_GO <= START[1] & copop; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 10. DP_FPU Top level of long operations datapath +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module DP_FPU( BCLK, FL, BRESET, LD_LDQ, WR_REG, BWD, FSR, OPCODE, SRC1, SRC2, START, DONE, UP_DP, WREN_L, + CLR_LSB, LD_OUT_L, DVZ_TRAP, DP_CMP, DP_OUT, DP_Q, TT_DP, CY_IN, OVF_BCD, COP_GO, COP_OP, + COP_IN, COP_DONE, COP_OUT ); + +input BCLK; +input FL; +input BRESET; +input LD_LDQ; +input WR_REG; +input [1:0] BWD; +input [8:3] FSR; +input [7:0] OPCODE; +input [31:0] SRC1; +input [31:0] SRC2; +input [1:0] START; +input CY_IN; +input COP_DONE; +input [23:0] COP_OP; +input [63:0] COP_IN; + +output DONE; +output UP_DP; +output WREN_L; +output CLR_LSB; +output LD_OUT_L; +output DVZ_TRAP; +output [2:0] DP_CMP; +output [31:0] DP_OUT; +output [31:0] DP_Q; +output [4:0] TT_DP; +output [3:0] OVF_BCD; +output COP_GO; +output [127:0] COP_OUT; + +reg [52:0] MDA; +reg [52:0] MDB; +reg [31:0] DP_Q; +reg [31:20] RCOPA,RCOPB; + +wire [63:0] DOUT; +wire [105:0] MRESULT; +wire MEI; +wire DFLOAT; +wire LOAD_MSD; +wire LOAD_LSD1; +wire LOAD_LSD2; +wire [31:0] LSD_1; +wire [31:0] LSD_2; +wire [52:32] MSD_1; +wire [52:32] MSD_2; + + +DP_LOGIK DOUBLE_U( + .FL(FL), + .BRESET(BRESET), + .BCLK(BCLK), + .WR_REG(WR_REG), + .BWD(BWD), + .FSR(FSR), + .MAN1(MDA[52:32]), + .MAN2(MDB[52:32]), + .MRESULT(MRESULT), + .OPCODE(OPCODE), + .SRC1(SRC1), + .SRC2(SRC2), + .START(START), + .MEI(MEI), + .DFLOAT(DFLOAT), + .DONE(DONE), + .UP_DP(UP_DP), + .CLR_LSB(CLR_LSB), + .WREN_L(WREN_L), + .LD_OUT_L(LD_OUT_L), + .DVZ_TRAP(DVZ_TRAP), + .DOUT(DOUT), + .DP_CMP(DP_CMP), + .TT_DP(TT_DP), + .CY_IN(CY_IN), + .OVF_BCD(OVF_BCD), + .COP_DONE(COP_DONE), + .COP_OP(COP_OP), + .COP_IN(COP_IN), + .COP_GO(COP_GO)); + +PREPDATA DP_PREP( + .MEI(MEI), + .DFLOAT(DFLOAT), + .BWD(BWD), + .SRC1(SRC1), + .SRC2(SRC2), + .START(START), + .LOAD_LSD1(LOAD_LSD1), + .LOAD_LSD2(LOAD_LSD2), + .LOAD_MSD(LOAD_MSD), + .LSD_1(LSD_1), + .LSD_2(LSD_2), + .MSD_1(MSD_1), + .MSD_2(MSD_2)); + + assign MRESULT = {21'd0,MDA[31:0]} * {21'd0,MDB[31:0]}; // unsigned multiplier 53 * 53 bits = 106 bits + + assign DP_OUT = CLR_LSB ? DP_Q : DOUT[63:32]; + + always@(posedge BCLK) if (LD_OUT_L || LD_LDQ || WREN_L) DP_Q <= LD_LDQ ? SRC2 : DOUT[31:0]; + + always@(posedge BCLK) if (LOAD_LSD1) MDA[31:0] <= LSD_1; + + always@(posedge BCLK) if (LOAD_LSD2) MDB[31:0] <= LSD_2; + + always@(posedge BCLK) + if (LOAD_MSD) + begin + MDA[52:32] <= MSD_1; + MDB[52:32] <= MSD_2; + RCOPA <= SRC1[31:20]; + RCOPB <= SRC2[31:20]; + end + + assign COP_OUT = {RCOPA,MDA[51:32],SRC1,RCOPB,MDB[51:32],SRC2}; + +endmodule diff --git a/src/m32632/ICACHE.v b/src/m32632/ICACHE.v new file mode 100644 index 0000000..a65925f --- /dev/null +++ b/src/m32632/ICACHE.v @@ -0,0 +1,421 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: ICACHE.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// ICACHE the instruction cache of M32632 +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module ICACHE( BCLK, MCLK, MDONE, BRESET, READ_I, IO_READY, PSR_USER, DATA_HOLD, PTB_WR, PTB_SEL, DRAM_WR, + KDET, HOLD, CFG, DRAM_Q, CINVAL, IC_SIGS, IO_Q, IVAR, KOLLI_A, MCR_FLAGS, MMU_DIN, VADR, WADDR, + WCTRL, IO_RD, DRAM_ACC, INIT_RUN, PROT_ERROR, ACC_OK, IC_PREQ, KOLLISION, ENA_HK, STOP_CINV, + DRAM_A, IC_DQ, IC_VA, ICTODC, IO_A, ENDRAM ); + +input BCLK; +input MCLK; +input MDONE; +input BRESET; +input READ_I; +input IO_READY; +input PSR_USER; +input DATA_HOLD; +input PTB_WR; +input PTB_SEL; +input DRAM_WR; +input KDET; +input HOLD; +input [1:0] CFG; +input [31:0] DRAM_Q; +input [1:0] CINVAL; +input [1:0] IC_SIGS; +input [31:0] IO_Q; +input [1:0] IVAR; +input [27:4] KOLLI_A; +input [3:0] MCR_FLAGS; +input [23:0] MMU_DIN; +input [31:0] VADR; +input [11:2] WADDR; +input [2:0] WCTRL; +input ENA_HK; +input ENDRAM; + +output IO_RD; +output DRAM_ACC; +output INIT_RUN; +output PROT_ERROR; +output ACC_OK; +output IC_PREQ; +output KOLLISION; +output STOP_CINV; +output [31:0] IC_DQ; +output [31:12] IC_VA; +output [3:0] ICTODC; +output reg [27:0] DRAM_A; +output reg [31:0] IO_A; + +reg [31:0] VADR_R; +reg [31:0] CAPDAT; +reg [31:0] DFFE_IOR; +reg HOLD_ON; +reg DFF_HDFF1; +reg DFF_IRD_REG; + +wire [4:0] A_CV; +wire ACOK; +wire [4:0] ACV; +wire AUX_DAT; +wire CA_HIT; +wire CA_SET; +wire CUPDATE; +wire [23:0] D_CV; +wire HIT_ALL; +wire INIT_CA_RUN; +wire IO_ACC; +wire KILL; +wire NEW_PTB; +wire PTB_ONE; +wire [31:12] RADR; +wire READ; +wire RUN_ICRD; +wire STOP_ICRD; +wire [23:0] UPCD; +wire [23:0] UPDATE_C; +wire [31:0] UPDATE_M; +wire USE_CA; +wire USER; +wire [11:7] V_ADR; +wire WE_CV; +wire WEMV; +wire WRCRAM0; +wire WRCRAM1; +wire WRSET0; +wire WRSET1; +wire WRITE; +wire [11:7] KILLADR; +wire AUX_ALT; +wire VIRT_A; +wire CI; +wire MMU_HIT; +wire LD_DRAM_A; +wire IO_SPACE; +wire LAST_MUX; +wire VIRTUELL; +wire NEW_PTB_RUN; +wire [31:0] SET_DAT; +wire [31:0] ALT_DAT; +wire [31:0] DAT_MV; +wire [3:0] RADR_MV; +wire [3:0] WADR_MV; +wire [23:0] NEWCVAL; +wire KILL_C,KILL_K; +wire RMW; + +// +++++++++++++++++++ Memories ++++++++++++++++++++ + +reg [31:0] DATA0 [0:1023]; // Data Set 0 : 4 kBytes +reg [31:0] SET_DAT0; + +reg [31:0] DATA1 [0:1023]; // Data Set 1 : 4 kBytes +reg [31:0] SET_DAT1; + +reg [15:0] TAGSET_0 [0:255]; // Tag Set for Data Set 0 : 256 entries of 16 bits +reg [15:0] TAG0; + +reg [15:0] TAGSET_1 [0:255]; // Tag Set for Data Set 1 : 256 entries of 16 bits +reg [15:0] TAG1; + +reg [23:0] CA_VALID [0:31]; // Valid bits for Data Set 0 and 1 : 32 entries of 24 bits +reg [23:0] CVALID; + +reg [35:0] MMU_TAGS [0:255]; // Tag Set for MMU : 256 entries of 36 bits +reg [35:0] MMU_Q; + +reg [31:0] MMU_VALID [0:15]; // Valid bits for MMU Tag Set : 16 entries of 32 bits +reg [31:0] MVALID; + +reg [15:0] KTAGSET_0 [0:255]; // Kollision Tag Set for Data Set 0 : 256 entries of 16 bits +reg [15:0] KTAG0; + +reg [15:0] KTAGSET_1 [0:255]; // Kollision Tag Set for Data Set 1 : 256 entries of 16 bits +reg [15:0] KTAG1; + +reg [23:0] KCA_VALID [0:31]; // Kollision Valid bits for Data Set 0 and 1 : 32 entries of 24 bits +reg [23:0] KCVALID; + +assign READ = READ_I & ~HOLD_ON & RUN_ICRD; +assign WRITE = 1'b0; +assign RMW = 1'b0; + +assign ALT_DAT = AUX_ALT ? DFFE_IOR : CAPDAT ; + +assign RADR = VIRT_A ? MMU_Q[19:0] : VADR_R[31:12] ; + +assign V_ADR = STOP_ICRD ? KILLADR : VADR[11:7] ; +assign ACV = STOP_ICRD ? KILLADR : A_CV ; +assign UPCD = STOP_ICRD ? NEWCVAL : UPDATE_C ; + +assign IC_DQ = LAST_MUX ? ALT_DAT : SET_DAT ; + +assign SET_DAT = CA_SET ? SET_DAT1 : SET_DAT0 ; + +assign KILL = KILL_C | KILL_K; + +assign IC_VA = VADR_R[31:12]; + +assign VIRT_A = ~CINVAL[0] & VIRTUELL; + +assign ACC_OK = HOLD_ON | ACOK; + +assign USER = ~MCR_FLAGS[3] & PSR_USER; + +assign AUX_ALT = HOLD_ON | DFF_IRD_REG; + +assign LAST_MUX = AUX_ALT | AUX_DAT; + +assign INIT_RUN = NEW_PTB_RUN | INIT_CA_RUN; + +assign LD_DRAM_A = ~DRAM_ACC | MDONE; + +assign ICTODC[3] = USER; + +always @(posedge BCLK) VADR_R <= VADR; + +always @(posedge BCLK) DFF_IRD_REG <= IO_RD; + +always @(posedge BCLK) DFF_HDFF1 <= IO_READY; + +always @(posedge BCLK) if (LD_DRAM_A) DRAM_A[27:0] <= {RADR[27:12],VADR_R[11:2],USE_CA,CA_SET}; + +always @(posedge BCLK) if (IO_ACC) IO_A <= {RADR[31:12],VADR_R[11:0]}; + +always @(posedge BCLK) if (IO_RD) DFFE_IOR <= IO_Q; + +always @(posedge BCLK or negedge BRESET) + if (!BRESET) HOLD_ON <= 1'b0; + else HOLD_ON <= (DATA_HOLD & DFF_HDFF1) | (HOLD_ON & DATA_HOLD); + +always @(posedge MCLK) if (WCTRL[2]) CAPDAT <= DRAM_Q; + +// +++++++++++++++++++++++++ Cache Valid +++++++++++++++++++ + +always @(posedge BCLK) CVALID <= CA_VALID[V_ADR[11:7]]; + +always @(negedge BCLK) if (WE_CV) CA_VALID[ACV] <= D_CV; + +// +++++++++++++++++++++++++ Tag Set 0 +++++++++++++++++++++ + +always @(posedge BCLK) TAG0 <= TAGSET_0[VADR[11:4]]; + +always @(negedge BCLK) if (WRCRAM0) TAGSET_0[VADR_R[11:4]] <= RADR[27:12]; + +// +++++++++++++++++++++++++ Tag Set 1 +++++++++++++++++++++ + +always @(posedge BCLK) TAG1 <= TAGSET_1[VADR[11:4]]; + +always @(negedge BCLK) if (WRCRAM1) TAGSET_1[VADR_R[11:4]] <= RADR[27:12]; + +// +++++++++++++++++++++++++ Data Set 0 ++++++++++++++++++++ + +always @(posedge BCLK) SET_DAT0 <= DATA0[VADR[11:2]]; + +always @(posedge MCLK) if (WRSET0) DATA0[WADDR] <= DRAM_Q; + +// +++++++++++++++++++++++++ Data Set 1 ++++++++++++++++++++ + +always @(posedge BCLK) SET_DAT1 <= DATA1[VADR[11:2]]; + +always @(posedge MCLK) if (WRSET1) DATA1[WADDR] <= DRAM_Q; + +CA_MATCH DCA_COMPARE( + .INVAL_L(CINVAL[0]), + .CI(CI), + .MMU_HIT(MMU_HIT), + .WRITE(WRITE), + .KDET(1'b0), + .ADDR({RADR[27:12],VADR_R[11:4]}), + .CFG(CFG), + .ENDRAM(ENDRAM), + .CVALID(CVALID), + .TAG0(TAG0), + .TAG1(TAG1), + .CA_HIT(CA_HIT), + .CA_SET(CA_SET), + .WB_ACC(), + .USE_CA(USE_CA), + .IOSEL(RADR[31:28]), + .IO_SPACE(IO_SPACE), + .DC_ILO(1'b0), + .KILL(KILL_C), + .UPDATE(UPDATE_C)); + +DCA_CONTROL DCA_CTRL( + .BCLK(BCLK), + .MCLK(1'b0), + .WRCFG(1'b1), + .BRESET(BRESET), + .CA_SET(CA_SET), + .HIT_ALL(HIT_ALL), + .UPDATE(UPCD), + .VADR_R(VADR_R[11:7]), + .DRAM_ACC(DRAM_ACC), + .CUPDATE(CUPDATE), + .KILL(KILL), + .WRITE(WRITE), + .WCTRL(WCTRL[1:0]), + .INVAL_A(CINVAL[1]), + .DAT_CV(D_CV), + .WADR_CV(A_CV), + .WE_CV(WE_CV), + .INIT_CA_RUN(INIT_CA_RUN), + .WRCRAM0(WRCRAM0), + .WRCRAM1(WRCRAM1), + .WRSET0(WRSET0), + .WRSET1(WRSET1)); + +ICACHE_SM IC_SM( + .BCLK(BCLK), + .BRESET(BRESET), + .IO_SPACE(IO_SPACE), + .READ(READ), + .MDONE(MDONE), + .IO_READY(IO_READY), + .MMU_HIT(MMU_HIT), + .CA_HIT(CA_HIT), + .USE_CA(USE_CA), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .USER(USER), + .PROT_ERROR(PROT_ERROR), + .PTE_ACC(IC_SIGS[1]), + .ACC_OK(ACOK), + .PTB_ONE(PTB_ONE), + .NEW_PTB(NEW_PTB), + .AUX_DAT(AUX_DAT), + .CUPDATE(CUPDATE), + .IO_RD(IO_RD), + .IO_ACC(IO_ACC), + .DRAM_ACC(DRAM_ACC), + .IC_PREQ(IC_PREQ), + .HIT_ALL(HIT_ALL)); + +// +++++++++++++++++++++++++ Kollision Valid +++++++++++++++ + +always @(posedge BCLK) KCVALID <= KCA_VALID[KOLLI_A[11:7]]; + +always @(negedge BCLK) if (WE_CV) KCA_VALID[ACV] <= D_CV; + +// +++++++++++++++++++++++++ Kollision Tag Set 0 +++++++++++ + +always @(posedge BCLK) KTAG0 <= KTAGSET_0[KOLLI_A[11:4]]; + +always @(negedge BCLK) if (WRCRAM0) KTAGSET_0[VADR_R[11:4]] <= RADR[27:12]; + +// +++++++++++++++++++++++++ Kollision Tag Set 1 +++++++++++ + +always @(posedge BCLK) KTAG1 <= KTAGSET_1[KOLLI_A[11:4]]; + +always @(negedge BCLK) if (WRCRAM1) KTAGSET_1[VADR_R[11:4]] <= RADR[27:12]; + +KOLDETECT KOLLOGIK( + .DRAM_WR(DRAM_WR), + .BCLK(BCLK), + .READ_I(READ_I), + .ACC_OK(ACC_OK), + .BRESET(BRESET), + .INVAL_A(CINVAL[1]), + .KDET(KDET), + .HOLD(HOLD), + .ENA_HK(ENA_HK), + .STOP_CINV(STOP_CINV), + .ADDR(KOLLI_A), + .C_VALID(KCVALID), + .CFG(CFG), + .CVALID(CVALID), + .TAG0(KTAG0), + .TAG1(KTAG1), + .KOLLISION(KOLLISION), + .STOP_ICRD(STOP_ICRD), + .RUN_ICRD(RUN_ICRD), + .KILL(KILL_K), + .ICTODC(ICTODC[2:0]), + .KILLADR(KILLADR), + .NEWCVAL(NEWCVAL)); + +MMU_MATCH MMU_COMPARE( + .USER(USER), + .READ(READ), + .WRITE(WRITE), + .RMW(RMW), + .IVAR(IVAR), + .MCR_FLAGS(MCR_FLAGS[2:0]), + .MMU_VA(MMU_Q[35:20]), + .MVALID(MVALID), + .VADR_R(VADR_R[31:12]), + .MMU_HIT(MMU_HIT), + .PROT_ERROR(PROT_ERROR), + .VIRTUELL(VIRTUELL), + .CI(CI), + .SEL_PTB1(), + .UPDATE(UPDATE_M)); + +MMU_UP MMU_CTRL( + .NEW_PTB(NEW_PTB), + .IVAR(IVAR[1]), + .BRESET(BRESET), + .PTB1(PTB_ONE), + .BCLK(BCLK), + .WR_MRAM(IC_SIGS[0]), + .MVALID(MVALID), + .UPDATE(UPDATE_M), + .VADR(VADR[19:16]), + .VADR_R(VADR_R[19:16]), + .WE_MV(WEMV), + .NEW_PTB_RUN(NEW_PTB_RUN), + .DAT_MV(DAT_MV), + .RADR_MV(RADR_MV), + .WADR_MV(WADR_MV)); + +// +++++++++++++++++++++++++ MMU Valid +++++++++++++++++++++ + +always @(posedge BCLK) MVALID <= MMU_VALID[RADR_MV]; + +always @(negedge BCLK) if (WEMV) MMU_VALID[WADR_MV] <= DAT_MV; + +// +++++++++++++++++++++++++ MMU Tags ++++++++++++++++++++++ + +always @(posedge BCLK) MMU_Q <= MMU_TAGS[VADR[19:12]]; + +always @(negedge BCLK) if (IC_SIGS[0]) MMU_TAGS[VADR_R[19:12]] <= {VADR_R[31:20],MMU_DIN[23:0]}; + +endmodule diff --git a/src/m32632/ICACHE_SM.v b/src/m32632/ICACHE_SM.v new file mode 100644 index 0000000..d97ff58 --- /dev/null +++ b/src/m32632/ICACHE_SM.v @@ -0,0 +1,359 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: ICACHE_SM.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. KOLDETECT Collision Detection Unit +// 2. ICACHE_SM Instruction Cache State Machine +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. KOLDETECT Collision Detection Unit +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module KOLDETECT ( BCLK, BRESET, DRAM_WR, CVALID, ADDR, TAG0, TAG1 , CFG , C_VALID, READ_I, ACC_OK, HOLD, KDET, INVAL_A, ENA_HK, + NEWCVAL, KOLLISION, STOP_ICRD, RUN_ICRD, KILL, KILLADR, ICTODC, STOP_CINV ); + + input BCLK; + input BRESET; + input DRAM_WR; + input [23:0] CVALID; // Data from master Valid RAM + input [27:4] ADDR; + input [27:12] TAG0,TAG1; + input [1:0] CFG; + input [23:0] C_VALID; // Data from secondary Valid RAM + input READ_I; + input ACC_OK; + input HOLD; // active low + input KDET; + input INVAL_A; // Cache Invalidate All + input ENA_HK; // Enable HOLD and Kohaerenz + + output [23:0] NEWCVAL; + output KOLLISION; + output STOP_ICRD; + output RUN_ICRD; + output KILL; + output [11:7] KILLADR; + output [2:0] ICTODC; + output STOP_CINV; + + reg [27:4] addr_r; + reg [7:0] maske,clear; + reg do_koll; + reg [2:0] counter; + reg [1:0] wpointer,rpointer; + reg [35:0] adrfifo; + reg [8:0] fifo_q,fifo_c; + reg [1:0] state; + reg pipe; + reg do_kill; + reg dma; + + wire [7:0] set_0,set_1; + wire match_0,match_1; + wire valid_0,valid_1; + wire found_0,found_1; + wire kolli,dma_kolli; + wire last_match; + wire wr_entry; + wire [23:0] cdaten; + wire [8:0] kaddr; + wire [7:0] new_0,new_1; + wire dma_mode,ic_dma; + wire free,ende; + wire init_b; + + always @(posedge BCLK) do_koll <= DRAM_WR & CFG[0]; // one cycle pulse, without Cache Enable no collision + always @(posedge BCLK) addr_r <= ADDR; + + // similar logic like in CA_MATCH + + assign set_0 = C_VALID[7:0]; + assign set_1 = C_VALID[15:8]; + + assign valid_0 = set_0[addr_r[6:4]]; + assign valid_1 = set_1[addr_r[6:4]]; + + assign match_0 = ( TAG0 == addr_r[27:12] ); // 4KB + assign match_1 = ( TAG1 == addr_r[27:12] ); // 4KB + + assign found_0 = valid_0 & match_0; + assign found_1 = valid_1 & match_1; + + assign kolli = (found_0 | found_1) & ~CFG[1] & do_koll; // Action only if ICACHE is not locked + + assign KOLLISION = (found_0 | found_1) & do_koll; // to Statistik Modul, Register there + + assign dma_kolli = (found_0 | found_1) & ~CFG[1] & CFG[0]; + + // the FIFO with 4 entries : + assign init_b = CFG[0] & ~INVAL_A; // initialise if CINV A too + + always @(posedge BCLK) + if (!init_b) wpointer <= 2'b00; + else + wpointer <= wpointer + {1'b0,wr_entry}; + + always @(posedge BCLK) + if (!init_b) rpointer <= 2'b00; + else + rpointer <= rpointer + {1'b0,do_kill}; + + always @(posedge BCLK) + begin + if (wr_entry && (wpointer == 2'b00)) adrfifo[8:0] <= {addr_r[11:4],found_1}; + if (wr_entry && (wpointer == 2'b01)) adrfifo[17:9] <= {addr_r[11:4],found_1}; + if (wr_entry && (wpointer == 2'b10)) adrfifo[26:18] <= {addr_r[11:4],found_1}; + if (wr_entry && (wpointer == 2'b11)) adrfifo[35:27] <= {addr_r[11:4],found_1}; + end + + always @(adrfifo or rpointer) + case (rpointer) + 2'b00 : fifo_q = adrfifo[8:0]; + 2'b01 : fifo_q = adrfifo[17:9]; + 2'b10 : fifo_q = adrfifo[26:18]; + 2'b11 : fifo_q = adrfifo[35:27]; + endcase + + always @(adrfifo or wpointer) // for Match of last entry use wpointer + case (wpointer) + 2'b01 : fifo_c = adrfifo[8:0]; + 2'b10 : fifo_c = adrfifo[17:9]; + 2'b11 : fifo_c = adrfifo[26:18]; + 2'b00 : fifo_c = adrfifo[35:27]; + endcase + + // Control + + assign last_match = counter[2] & (fifo_c == {addr_r[11:4],found_1}); // if Match with last Entry no new Entry + + assign wr_entry = kolli & ~last_match; + + always @(posedge BCLK) + casex ({init_b,wr_entry,do_kill,counter}) + 6'b0_xx_xxx : counter <= 3'b000; + 6'b1_00_xxx : counter <= counter; + 6'b1_11_xxx : counter <= counter; + 6'b1_10_000 : counter <= 3'b100; + 6'b1_10_1xx : counter <= (counter[1:0] == 2'b11) ? 3'b111 : {counter[2],(counter[1:0] + 2'b01)}; // Overflow avoid + 6'b1_01_1xx : counter <= (counter[1:0] == 2'b00) ? 3'b000 : {counter[2],(counter[1:0] + 2'b11)}; + default : counter <= counter; + endcase + + // DMA Access + always @(posedge BCLK) dma <= ~HOLD; // there is only one FF for this , from here to DCACHE + + // Controlling of ICACHE + + assign free = (~READ_I | ACC_OK) & ENA_HK; // switch off if CINV + + always @(posedge BCLK) // state[1] state[0] + casex ({BRESET,dma,counter[2],free,ende,STOP_ICRD,dma_mode}) + 7'b0_xx_xx_xx : state <= 2'b00; + 7'b1_00_xx_00 : state <= 2'b00; + 7'b1_01_1x_00 : state <= 2'b10; // Start of DCACHE Kohaerenz + 7'b1_1x_1x_00 : state <= 2'b11; // Start of DMA + // + 7'b1_xx_x0_10 : state <= 2'b10; // without "ende" it stays as is + 7'b1_0x_x1_10 : state <= 2'b00; // DMA is not active + 7'b1_1x_x1_10 : state <= 2'b11; // to DMA ! + // + 7'b1_00_xx_11 : state <= 2'b00; + 7'b1_01_xx_11 : state <= 2'b10; + 7'b1_1x_xx_11 : state <= 2'b11; + default : state <= 2'b00; + endcase + + assign STOP_ICRD = state[1]; // used for Multiplexer + assign dma_mode = state[0]; // internal Multiplexer + + assign STOP_CINV = state[1] & ~ENA_HK; // stops CINV if DMA access or Kohaerenz access + + assign ende = (counter[1:0] == 2'b00) & do_kill; + + assign ic_dma = STOP_ICRD & dma_mode; // Signal to DCACHE that ICACHE has stoped + + always @(posedge BCLK) pipe <= STOP_ICRD; + + assign RUN_ICRD = ~(STOP_ICRD | pipe); // Release for IC_READ + + always @(posedge BCLK) do_kill <= STOP_ICRD & ~dma_mode & ~do_kill; // Write pulse in Cache Valid RAM, 1 cycle on, 1 cycle off + + assign KILL = do_kill | (KDET & dma_kolli); + + // Valid Daten prepare : different sources for DMA and DCACHE Kohaerenz + + assign cdaten = dma_mode ? C_VALID : CVALID; + assign kaddr = dma_mode ? {addr_r[11:4],found_1} : fifo_q; + + assign KILLADR = kaddr[8:4]; + + always @(kaddr) + case (kaddr[3:1]) + 3'h0 : clear = 8'hFE; + 3'h1 : clear = 8'hFD; + 3'h2 : clear = 8'hFB; + 3'h3 : clear = 8'hF7; + 3'h4 : clear = 8'hEF; + 3'h5 : clear = 8'hDF; + 3'h6 : clear = 8'hBF; + 3'h7 : clear = 8'h7F; + endcase + + assign new_0 = kaddr[0] ? cdaten[7:0] : (cdaten[7:0] & clear); + assign new_1 = kaddr[0] ? (cdaten[15:8] & clear) : cdaten[15:8]; + + assign NEWCVAL = {cdaten[23:16],new_1,new_0}; + + // multiple signals are needed in DCACHE : + assign ICTODC = {dma,ic_dma,~(counter[2:1] == 2'b11)}; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. ICACHE_SM Instruction Cache State Machine +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ICACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, PTE_ACC, + USE_CA, PTB_WR, PTB_SEL, USER, PROT_ERROR, + DRAM_ACC, IO_RD, IO_ACC, IC_PREQ, ACC_OK, HIT_ALL, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE ); + + input BCLK; + input BRESET; + input IO_SPACE; + input MDONE; // Memory Done : Feedback from DRAM Controller, BCLK aligned + input IO_READY; + input MMU_HIT,CA_HIT; + input READ; + input PTE_ACC; + input USE_CA; + input PTB_WR,PTB_SEL; + input USER; + input PROT_ERROR; + + output reg DRAM_ACC,IO_RD; + output IO_ACC; + output IC_PREQ; + output ACC_OK; + output HIT_ALL; + output CUPDATE; + output AUX_DAT; + output reg NEW_PTB,PTB_ONE; + + reg [3:0] new_state; + reg rd_done; + reg card_flag; + reg rd_rdy; + + wire io_busy; + wire dram_go; + wire rd_ende; + wire do_ca_rd; + +// Cycle : /-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_ +// Access : _/-----------------------------------\__ +// State Machine : ____/----------------------------\______ +// Busy status ... + + assign rd_ende = CA_HIT | rd_rdy; // CA_HIT only if Cache activ ! + + always @( READ // only READ , global control + or PROT_ERROR // is not allowed ! + // + or IO_SPACE // indicates access in the IO_WELT + or io_busy // is already active ? + // + or MMU_HIT // Hit in the MMU , now only a READ can be active + or rd_ende // Cache Hit + or DRAM_ACC // DRAM Access running + // + or PTE_ACC ) // PTE Access running + // #_# #_# #_# + casex ({READ,PROT_ERROR,IO_SPACE,io_busy,MMU_HIT,rd_ende,DRAM_ACC,PTE_ACC}) + // MMU Miss : PTE load from memory + 8'b10_xx_0xx_0 : new_state = 4'b0100; // start PTE access + // IO-Address selected : external access starts if not already BUSY + 8'b10_10_1xx_x : new_state = 4'b0001; + // DRAM Access : Cache Miss at READ + 8'b10_0x_100_x : new_state = 4'b1010; // can start directly + default : new_state = 4'b0; + endcase + + assign IO_ACC = new_state[0]; // to load the Register for Data and Addr + assign dram_go = new_state[1]; + assign IC_PREQ = new_state[2]; // MMU to DCACHE ! + assign do_ca_rd = new_state[3]; + + assign HIT_ALL = MMU_HIT & CA_HIT; // for Update "Last-Set" , MMU_HIT contains ZUGRIFF + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) card_flag <= 1'b0; + else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE); + + assign CUPDATE = card_flag & USE_CA & MDONE; // USE_CA = ~CI & ~LDC; + + always @(posedge BCLK) rd_rdy <= card_flag & MDONE; + + // The cache RAM can not provide fast enough the data after an Update. In this case a secondary data path is activated + assign AUX_DAT = rd_rdy; + + // DRAM Interface : + + always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1; + else + DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET; + // IO Interface : + + always @(posedge BCLK) + begin + if (IO_ACC) IO_RD <= READ; else IO_RD <= IO_RD & ~IO_READY & BRESET; + end + + assign io_busy = IO_RD | rd_done; // access is gone in next clock cycle, therefore blocked with "rd_done" + + always @(posedge BCLK) rd_done <= READ & IO_READY; // For READ one clock later for data to come through + + // global feedback to opcode fetch unit : you can continue + + assign ACC_OK = IO_SPACE ? rd_done : (READ & MMU_HIT & rd_ende); + + // PTB1 und PTB0 + + always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block + always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL; + +endmodule diff --git a/src/m32632/I_PFAD.v b/src/m32632/I_PFAD.v new file mode 100644 index 0000000..7a2de3a --- /dev/null +++ b/src/m32632/I_PFAD.v @@ -0,0 +1,849 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: I_PFAD.v +// Version: 1.2 bug fix +// Version: 1.1 bug fix release of 7 November 2015 +// History: 1.0 first release of 30 Mai 2015 +// Date: 4 February 2016 +// +// Copyright (C) 2016 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. BITMASK Mask Generator , was a ROM on falling edge in early days +// 2. MULFILTER Filter for Multiplier Input Data +// 3. SIGNMUL Signed Multiplier for Integer Multiplication +// 4. SHIFTER Barrel Shifter for all Shift Opcodes +// 5. FFS_LOGIK Logic for FFS opcode +// 6. SCHALE Enclosure for Adder/Subtractor +// 7. I_PFAD The Integer Datapath +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. BITMASK Mask Generator , was a ROM on falling edge in early days +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module BITMASK (AA, DOUT); + +// 0 : FFFFFFFF; Masktype 1 , Zero from right +// 1 : FFFFFFFE; +// 2 : FFFFFFFC; +// 3 : FFFFFFF8; +// . : ... +// 32 : 00000001; Masktype 2 , Decoder +// 33 : 00000002; +// 34 : 00000004; +// 35 : 00000008; +// .. : ... +// 64 : 00000001; Masktyte 3 , One from right +// 65 : 00000003; +// 66 : 00000007; +// 67 : 0000000F; +// .. : ... +// 96 : FFFFFFFF; Masktype 4 , like Masktype 3 but AA-1 +// 97 : 00000001; +// 98 : 00000003; +// 99 : 00000007; +// .. : ... + + input [6:0] AA; + + output reg [31:0] DOUT; + + reg [7:0] dec_bit; + + wire [4:0] code; + wire high,low; + + + assign code = AA[4:0] - {4'd0,&AA[6:5]}; + + assign high = (AA[6:5] == 2'd0); + assign low = AA[6]; + + always @(code or high or low) + case (code[2:0]) + 3'b000 : dec_bit = {{7{high}},1'b1 }; + 3'b001 : dec_bit = {{6{high}},1'b1, low }; + 3'b010 : dec_bit = {{5{high}},1'b1,{2{low}}}; + 3'b011 : dec_bit = {{4{high}},1'b1,{3{low}}}; + 3'b100 : dec_bit = {{3{high}},1'b1,{4{low}}}; + 3'b101 : dec_bit = {{2{high}},1'b1,{5{low}}}; + 3'b110 : dec_bit = { high ,1'b1,{6{low}}}; + 3'b111 : dec_bit = { 1'b1,{7{low}}}; + endcase + + always @(code or high or low or dec_bit) + case (code[4:3]) + 2'b00 : DOUT = {{24{high}},dec_bit }; + 2'b01 : DOUT = {{16{high}},dec_bit,{ 8{low}}}; + 2'b10 : DOUT = {{ 8{high}},dec_bit,{16{low}}}; + 2'b11 : DOUT = { dec_bit,{24{low}}}; + endcase + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. MULFILTER Filter for Multiplier Input Data +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module MULFILTER (BWD, FLOAT, SRC1, SRC2, DEST1, DEST2); + + input [1:0] BWD; + input FLOAT; + input [31:0] SRC1,SRC2; + output [31:0] DEST1,DEST2; + + wire sign1,sign2; + reg [31:0] DEST1,DEST2; + + assign sign1 = BWD[0] ? SRC1[15] : SRC1[7]; + + always @(FLOAT or BWD or SRC1 or sign1) + casex ({FLOAT,BWD,sign1}) + 4'b0_00_0 : DEST1 = {24'h000000, SRC1[7:0]}; + 4'b0_00_1 : DEST1 = {24'hFFFFFF, SRC1[7:0]}; + 4'b0_01_0 : DEST1 = { 16'h0000,SRC1[15:0]}; + 4'b0_01_1 : DEST1 = { 16'hFFFF,SRC1[15:0]}; + 4'b1_xx_x : DEST1 = { 9'h001,SRC1[22:0]}; + default : DEST1 = SRC1; + endcase + + assign sign2 = BWD[0] ? SRC2[15] : SRC2[7]; + + always @(FLOAT or BWD or SRC2 or sign2) + casex ({FLOAT,BWD,sign2}) + 4'b0_00_0 : DEST2 = {24'h000000, SRC2[7:0]}; + 4'b0_00_1 : DEST2 = {24'hFFFFFF, SRC2[7:0]}; + 4'b0_01_0 : DEST2 = { 16'h0000,SRC2[15:0]}; + 4'b0_01_1 : DEST2 = { 16'hFFFF,SRC2[15:0]}; + 4'b1_xx_x : DEST2 = { 9'h001,SRC2[22:0]}; + default : DEST2 = SRC2; + endcase + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. SIGNMUL Signed Multiplier for Integer Multiplication +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SIGNMUL (dataa, datab, result); + + input signed [31:0] dataa,datab; + output signed [63:0] result; + + assign result = dataa * datab; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. SHIFTER Barrel Shifter for all Shift Opcodes +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SHIFTER ( MASKE,ROT,LSH,ASH,SIZE,SH_VAL,SH_DAT,SH_OUT,MASK_SEL); + + input [31:0] MASKE; + input ROT,LSH,ASH; + input [1:0] SIZE; + input [7:0] SH_VAL; + input [31:0] SH_DAT; + output [31:0] SH_OUT; + output [4:0] MASK_SEL; + + reg [31:0] sh_dat_in; + wire [31:0] sh_dat_0,sh_dat_1,sh_dat_2,sh_dat_3,sh_dat_4; + wire [4:0] shift; + reg msb; + wire [1:0] mask_code; + reg [31:0] SH_OUT; + reg [4:0] MASK_SEL; + + // Inputstage : prepare for ROT opcode : + + always @(ROT or SIZE or SH_DAT) + casex ({ROT,SIZE}) + 3'b100 : sh_dat_in = {SH_DAT[31:16],SH_DAT[7:0],SH_DAT[7:0]}; // Byte copy to left + 3'b101 : sh_dat_in = {SH_DAT[15:0],SH_DAT[15:0]}; // Word copy to left + default : sh_dat_in = SH_DAT; + endcase + + // Special case for ROT and BYTE : this way less logic + + assign shift = (ROT & (SIZE == 2'b00)) ? {2'b11,SH_VAL[2:0]} : SH_VAL[4:0]; + + // Rotation logic + + assign sh_dat_0 = shift[0] ? {sh_dat_in[30:0],sh_dat_in[31]} : sh_dat_in; // Rotation of 1 bit position + assign sh_dat_1 = shift[1] ? {sh_dat_0[29:0],sh_dat_0[31:30]} : sh_dat_0; // 2 + assign sh_dat_2 = shift[2] ? {sh_dat_1[27:0],sh_dat_1[31:28]} : sh_dat_1; // 4 + assign sh_dat_3 = shift[3] ? {sh_dat_2[23:0],sh_dat_2[31:24]} : sh_dat_2; // 8 + assign sh_dat_4 = shift[4] ? {sh_dat_3[15:0],sh_dat_3[31:16]} : sh_dat_3; // 16 + + // Detection of negativ data + + always @(SIZE or SH_DAT) + casex (SIZE) + 2'b00 : msb = SH_DAT[7]; // Byte + 2'b01 : msb = SH_DAT[15]; // Word + default : msb = SH_DAT[31]; // Double = 11 + endcase + + // needs mask for output data : SH_VAL[7] says negativ number and "right" shift + + assign mask_code[1] = ROT | (SH_VAL[7] & ASH & msb); + assign mask_code[0] = ROT | (SH_VAL[7] & ((ASH & ~msb) | LSH)); + + always @(SH_VAL or SIZE) + casex ({SH_VAL[7],SIZE}) + 3'b100 : MASK_SEL = {2'b00,SH_VAL[2:0]}; // special mask for Byte at right-shift + 3'b101 : MASK_SEL = {1'b0,SH_VAL[3:0]}; // special mask for Word at right-shift + default : MASK_SEL = SH_VAL[4:0]; + endcase + + always @(mask_code or sh_dat_4 or MASKE) // top bits of MASKE are "1", lower bits are "0" + casex (mask_code) + 2'b00 : SH_OUT = sh_dat_4 & MASKE; // LSH and ASH with positiv shift count + 2'b01 : SH_OUT = sh_dat_4 & ~MASKE; // Negativ shift count : LSH or ASH with positiv data + 2'b10 : SH_OUT = sh_dat_4 | MASKE; // ASH with negativ shift count and negativ input data + default : SH_OUT = sh_dat_4; // ROT + endcase + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 5. FFS_LOGIK Logic for FFS opcode +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module FFS_LOGIK (SRC1, SRC2, BWD, FLAG, DOUT); + + input [31:0] SRC1; + input [4:0] SRC2; + input [1:0] BWD; + output reg FLAG; + output [4:0] DOUT; + + reg [6:0] maske; + reg [7:0] byte_1,byte_2; + + wire [7:0] byte_0,byte_3; + wire [15:0] mdat_0; + wire [7:0] mdat_1; + wire [3:0] mdat_2; + wire [1:0] mdat_3; + wire [4:0] obits; + + always @(*) + case (SRC2[2:0]) + 3'd0 : maske = 7'h7F; + 3'd1 : maske = 7'h7E; + 3'd2 : maske = 7'h7C; + 3'd3 : maske = 7'h78; + 3'd4 : maske = 7'h70; + 3'd5 : maske = 7'h60; + 3'd6 : maske = 7'h40; + 3'd7 : maske = 7'h00; + endcase + + assign byte_0 = (SRC2[4:3] == 2'b00) ? {SRC1[7],(SRC1[6:0] & maske)} : 8'h00; + + always @(*) + casex (SRC2[4:3]) + 2'b00 : byte_1 = SRC1[15:8]; + 2'b01 : byte_1 = {SRC1[15],(SRC1[14:8] & maske)}; + 2'b1x : byte_1 = 8'h00; + endcase + + always @(*) + casex (SRC2[4:3]) + 2'b0x : byte_2 = SRC1[23:16]; + 2'b10 : byte_2 = {SRC1[23],(SRC1[22:16] & maske)}; + 2'b11 : byte_2 = 8'h00; + endcase + + assign byte_3 = (SRC2[4:3] == 2'b11) ? {SRC1[31],(SRC1[30:24] & maske)} : SRC1[31:24]; + + assign obits[4] = ({byte_1,byte_0} == 16'h0); + assign mdat_0 = obits[4] ? {byte_3,byte_2} : {byte_1,byte_0}; // 16 Bit + + assign obits[3] = (mdat_0[7:0] == 8'h0); + assign mdat_1 = obits[3] ? mdat_0[15:8] : mdat_0[7:0]; + + assign obits[2] = (mdat_1[3:0] == 4'h0); + assign mdat_2 = obits[2] ? mdat_1[7:4] : mdat_1[3:0]; + + assign obits[1] = (mdat_2[1:0] == 2'b0); + assign mdat_3 = obits[1] ? mdat_2[3:2] : mdat_2[1:0]; + + assign obits[0] = ~mdat_3[0]; + + always @(BWD or obits or mdat_3) + casex ({BWD,obits[4:3]}) + 4'b00_x1 : FLAG = 1; // Byte Overflow => nothing found + 4'b00_10 : FLAG = 1; // Byte Overflow => nothing found + 4'b01_1x : FLAG = 1; // Word Overflow => nothing found + default : FLAG = (mdat_3 == 2'b00); + endcase + + assign DOUT = FLAG ? 5'h0 : obits; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 6. SCHALE Enclosure for Adder/Subtractor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SCHALE (dataa, datab, cin, add_sub, bwd, result, cout, overflow); + + input [31:0] dataa,datab; + input cin; + input add_sub; // 1 = Addition , 0 = Subtraction + input [1:0] bwd; + + output [31:0] result; + output cout,overflow; + + reg [2:0] seldat; + reg overflow; + + wire [32:0] summe; + + assign summe = {1'b0,dataa} + {1'b0,(add_sub ? datab : ~datab)} + {32'd0,cin}; + + always @(bwd or dataa or datab or summe) + case (bwd) + 2'b00 : seldat = {summe[7], dataa[7], datab[7]}; + 2'b01 : seldat = {summe[15],dataa[15],datab[15]}; + default : seldat = {summe[31],dataa[31],datab[31]}; + endcase + + always @(seldat or add_sub) + case (seldat[1:0]) + 2'b00 : overflow = add_sub ? seldat[2] : 1'b0; + 2'b01 : overflow = add_sub ? 1'b0 : seldat[2]; + 2'b10 : overflow = add_sub ? 1'b0 : ~seldat[2]; + 2'b11 : overflow = add_sub ? ~seldat[2] : 1'b0; + endcase + + assign cout = add_sub ? summe[32] : ~summe[32]; + assign result = summe[31:0]; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 7. I_PFAD The Integer Datapath +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module I_PFAD ( BCLK, BRESET, SFP_DAT, FSR, DP_OUT, SRC1, SRC2, BMASKE, ADDR, MRESULT, OPCODE, BWD, FL, SP_CMP, DP_CMP, LD_OUT, + WREN, WRADR, RDAA, DETOIP, BITSEL, OVF_BCD, DISP, RWVFLAG, DSR, I_OUT, PSR, BMCODE, OV_FLAG, ACB_ZERO, STRING); + + input BCLK,BRESET; + input [31:0] SFP_DAT,FSR,DP_OUT; + input [31:0] SRC1,SRC2; + input [31:0] BMASKE; + input [31:0] ADDR; + input [63:0] MRESULT; + input [7:0] OPCODE; + input [1:0] BWD; + input FL; + input [2:0] SP_CMP; + input [2:0] DP_CMP; + input LD_OUT; + input WREN; + input [5:0] WRADR; + input [7:0] RDAA; + input [11:0] DETOIP; + input [2:0] BITSEL; + input [3:0] OVF_BCD; + input [4:0] DISP; + input RWVFLAG; + input [3:0] DSR; + + output [31:0] I_OUT; + output [11:0] PSR; + output [6:0] BMCODE; // ROM Address for BITMASK + output reg OV_FLAG; + output ACB_ZERO; + output [4:0] STRING; + + reg [31:0] I_OUT; + reg [31:0] pfad_7,pfad_6,pfad_8,pfad_4a; + wire [31:0] pfad_4,pfad_5,pfad_11; + + reg [31:0] bwd_daten1,bwd_daten2; + wire [31:0] addsub_q; + + // +++++++++++++ Global Output Multiplexer ++++++++++++++++++++++++++++ + + always @(OPCODE or pfad_4 or pfad_5 or pfad_6 or pfad_7 or pfad_8 or DP_OUT or FL or SFP_DAT or FSR or pfad_11) + casex (OPCODE[7:3]) + 5'b0100_x : I_OUT = pfad_4; + 5'b0101_x : I_OUT = pfad_5; // String opcodes + 5'b0110_x : I_OUT = pfad_6; + 5'b0111_x : I_OUT = pfad_7; + 5'b1000_x : I_OUT = pfad_8; + 5'b1001_0 : I_OUT = DP_OUT; // SP_FPU has higher priority ! LFSR has no output + // SFSR : ROUND,TRUNC,FLOOR Integer Data : SP or DP Block + 5'b1001_1 : I_OUT = (OPCODE[2:1] == 2'b10) ? FSR : (FL ? SFP_DAT : DP_OUT); + 5'b1011_x : I_OUT = pfad_11; + 5'b1101_x : I_OUT = DP_OUT; // Coprocessor + default : I_OUT = 32'hxxxx_xxxx; // don't care + endcase + + // ++++++++++++++ PSR Register : I P S U / N Z F V - L T C + // 11 10 9 8 7 6 5 4 3 2 1 0 + + reg [3:0] psr_high; + reg [7:0] psr_low,psr_new; + reg [11:0] push_psr; // true Register + reg [11:0] calc_psr; // only verilog case + reg [1:0] nl_int; + + wire ld_psr_l,ld_psr_h,up_psr; + wire cmp_op,bit_op,ari_op,neg_op,ffs_op,str_op,chk_op,abs_op,rwv_op; + wire [1:0] fp_nz; + wire f_flag,z_flag; + wire [1:0] nl_flags; + wire over_flow,cy_out; + wire ffs_flag; // FLAG result of FFS + wire chk_flag; // FLAG result of CHECK + wire save_psr,pop_psr; + wire [4:0] selbits; + // Bits from DETOIP; + wire cmps_op,ph_match,until,kill_opt,inss_op,exin_cmd,extract,bit_reg,kurz_st,dw_info,acb_reg,t2p; + wire bcd_op,bcd_carry; + + assign cmps_op = DETOIP[11]; // for CMPS + assign ph_match = DETOIP[10]; // MATCH phase + assign until = DETOIP[9]; // UNITL Flag for String + assign kill_opt = DETOIP[8]; // optimized execution of MOVS/MOVM + assign inss_op = DETOIP[7]; // 1=INSS + assign exin_cmd = DETOIP[6]; // for EXT/INS + assign extract = DETOIP[5] & exin_cmd; // 1=EXT + assign bit_reg = DETOIP[4]; // for Bit opcodes + assign kurz_st = DETOIP[3]; // for MOVM/CMPM + assign dw_info = DETOIP[2]; // at ADJSPi is SP=SRC2 always 32 Bit + assign acb_reg = DETOIP[1]; // suppresses Carry-Set at ACB + assign t2p = DETOIP[0]; // Pulse to Load Trace-Bit to Pending-Trace-Bit + + assign bcd_op = OVF_BCD[1]; // ADDPi,SUBPi - from DP_FPU + assign bcd_carry = OVF_BCD[0]; + + assign ld_psr_l = ((WRADR == 6'h1D) | (WRADR == 6'h10)) & WREN; // Register PSR & UPSR + assign ld_psr_h = (WRADR == 6'h1D) & (BWD != 2'b00) & WREN; // Register PSR + // LD_OUT[1] is coming out of DECODER for this purpose + assign up_psr = bcd_op | ((cmp_op | bit_op | ari_op | neg_op | ffs_op | chk_op) & LD_OUT); + + assign cmp_op = (OPCODE == 8'h41) | ((OPCODE == 8'hB2) & (FL ? ~SP_CMP[2] : ~DP_CMP[2])); // CMPi or (CMPf & ~NAN) + assign bit_op = ((OPCODE[7:4] == 4'h6) & ((~OPCODE[3] & OPCODE[1]) | OPCODE[3:0] == 4'hE)) // the last term is for IBIT + | (OPCODE == 8'h4D) | str_op | rwv_op; // TBIT or CMPS or RDVAL/WRVAL + assign ari_op = (OPCODE[7:4] == 4'h4) & (OPCODE[1:0] == 2'b0) & ~dw_info; // ADDi,ADDCi,SUBi,SUBCi - special case ADJSPi no flags + assign neg_op = (OPCODE[7:4] == 4'h6) & (OPCODE[3] & (OPCODE[1:0] == 2'b0)); // ABSi,NEGi + assign ffs_op = (OPCODE == 8'h85); // FFS + assign chk_op = (OPCODE == 8'h83); // CHECK + assign str_op = (OPCODE[7:4] == 4'h5) & (OPCODE[3:2] == 2'b0) & ~kurz_st; // String-"S" opcodes : F-Flag to 0, at start always + assign abs_op = (OPCODE == 8'h6C); // ABSi : Carry is not affected ! + assign rwv_op = (OPCODE[7:4] == 4'hE) & (OPCODE[3:1] == 3'b0); // RDVAL + WRVAL + + always @(bwd_daten1 or bwd_daten2 or addsub_q) // SRC1 > SRC2 ? + case ({bwd_daten2[31],bwd_daten1[31]}) + 2'b00 : nl_int = {addsub_q[31],addsub_q[31]}; // MSB = N , LSB = L + 2'b01 : nl_int = { 1'b0 , 1'b1 }; + 2'b10 : nl_int = { 1'b1 , 1'b0 }; + 2'b11 : nl_int = {addsub_q[31],addsub_q[31]}; + endcase + + assign ACB_ZERO = (addsub_q == 32'h0); // is used for ACBi opcode too + assign f_flag = str_op ? 1'b0 : (rwv_op ? RWVFLAG : (bit_op ? SRC2[selbits] : (acb_reg ? PSR[5] : over_flow))); + assign fp_nz = FL ? SP_CMP[1:0] : DP_CMP[1:0]; + assign z_flag = OPCODE[1] ? fp_nz[0] : ACB_ZERO; + assign nl_flags = OPCODE[1] ? {fp_nz[1],1'b0} : nl_int; + + always @(*) // Bits : N Z F V - L T C + casex ({cmp_op,bcd_op,bit_op,(ffs_op | chk_op)}) + 4'b0000 : psr_new = {PSR[7:6], f_flag,PSR[4:1],((acb_reg | abs_op) ? PSR[0] : cy_out)}; // arithmetic Op : CY and F + 4'b0001 : psr_new = {PSR[7:6],(ffs_op ? ffs_flag : chk_flag),PSR[4:0]}; // FFS or CHECK + 4'b001x : psr_new = (cmps_op & str_op) ? + {2'b01, f_flag,PSR[4:3],1'b0,PSR[1:0]} // Init CMPS + : {PSR[7:6], f_flag,PSR[4:0]}; // Bit opcode + 4'b01xx : psr_new = {PSR[7:6], 1'b0, PSR[4:1],bcd_carry}; // BCD opcode + 4'b1xxx : psr_new = ph_match ? + {PSR[7:6], ~(ACB_ZERO ^ until), PSR[4:0]} // Until/While Option at String-"S" opcodes + : {nl_flags[1],z_flag,PSR[5:3], nl_flags[0],PSR[1:0]}; // CMP f or i + endcase + + always @(save_psr or pop_psr or OPCODE or PSR or SRC1) + casex ({save_psr,pop_psr,OPCODE[6],OPCODE[2]}) + 4'b10xx : calc_psr = PSR & {~OPCODE[0],11'h0ED}; // clear P S U V T and the I-Bit at Interrupt & ABORT + 4'b11xx : calc_psr = SRC1[27:16]; + 4'b0x00 : calc_psr = PSR & ~SRC1[11:0]; // BICPSR : Opcode = h32 + 4'b0x01 : calc_psr = PSR | SRC1[11:0]; // BISPSR h36 + default : calc_psr = SRC1[11:0]; // LPR PSR h76 + endcase + + // Special case Exception Handling : Code x'89-x'8F + assign save_psr = (OPCODE[7:3] == 5'b1000_1); + assign pop_psr = (OPCODE[2:0] == 3'b000); + + always @(posedge BCLK or negedge BRESET) // central memory for PSR low + if (!BRESET) psr_low <= 8'h0; + else + begin + if (ld_psr_l || save_psr) psr_low <= calc_psr[7:0]; + else + if (up_psr) psr_low <= psr_new; // the Status result of a normal opcode + end + + always @(posedge BCLK or negedge BRESET) // central memory for PSR high + if (!BRESET) psr_high <= 4'h0; + else + begin + if (ld_psr_h || save_psr) psr_high <= calc_psr[11:8]; // only at WORD access + else // t2p : copy T-Bit into P-Bit at the beginning of opcode + if (t2p) psr_high <= {psr_high[3],psr_low[1],psr_high[1:0]}; + end + + // Register for storage of PSR at Entry of Exception + always @(posedge BCLK) if (save_psr) push_psr <= {PSR[11],(~OPCODE[1] & PSR[10]),PSR[9:0]}; // P-Flag modified + + assign PSR = {psr_high,psr_low}; + + // ++++++++++++++ Overflow Detection ++++++++++++++++++++++++++++++++++++++ + + reg ovf_mul,ovf_ash; + wire [31:0] shdat; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) OV_FLAG <= 1'b0; + else + if (OVF_BCD[3]) OV_FLAG <= OVF_BCD[2]; // DEI,QUO,DIV + else + if (LD_OUT) + case (OPCODE) + 8'h78 : OV_FLAG <= ovf_mul; + 8'h61 : OV_FLAG <= ovf_ash; + 8'h40 : OV_FLAG <= over_flow & acb_reg; // ADD Opcode at ACB + default : OV_FLAG <= 1'b0; + endcase + + always @(BWD or MRESULT) + casex (BWD) + 2'b00 : ovf_mul = ~((MRESULT[15:7] == 9'd0) | (MRESULT[15:7] == 9'h1FF)); + 2'b01 : ovf_mul = ~((MRESULT[31:15] == 17'd0) | (MRESULT[31:15] == 17'h1FFFF)); + default : ovf_mul = ~((MRESULT[63:31] == 33'd0) | (MRESULT[63:31] == 33'h1FFFFFFFF)); + endcase + + always @(BWD or SRC2 or shdat) + casex (BWD) + 2'b00 : ovf_ash = (SRC2[7] != shdat[7]); + 2'b01 : ovf_ash = (SRC2[15] != shdat[15]); + default : ovf_ash = (SRC2[31] != shdat[31]); + endcase + + // ++++++++++++++ Format 4 Opcodes : Basic Integer Opcodes, MOVi is special case +++++++++++++ + + reg cy_in; + reg get_psr,rd_psr,rd_dsr,get_mod; + wire add_flag; + + always @(BWD or SRC1) + casex (BWD) + 2'b00 : bwd_daten1 = {{24{SRC1[7]}}, SRC1[7:0]}; // Sign Extension + 2'b01 : bwd_daten1 = {{16{SRC1[15]}},SRC1[15:0]}; + default : bwd_daten1 = SRC1; + endcase + + assign add_flag = ~OPCODE[3] & ~OPCODE[1] & ~OPCODE[0]; // Only ADDi and ADDCi otherwise subtract in SCHALE + + always @(PSR or OPCODE) // more effort due to ABSi und NEGi : Format 6 + casex ({OPCODE[5],OPCODE[3:2]}) + 3'b000 : cy_in = OPCODE[0]; // ADD + CMP + 3'b001 : cy_in = PSR[0]; // ADDC + 3'b011 : cy_in = ~PSR[0]; // SUBC + default : cy_in = 1'b1; // SUB + ABS + NEG : BORROW must be 1 for normal Adder + endcase + + SCHALE addsub_ipfad (.dataa(bwd_daten2), .datab(bwd_daten1), .cin(cy_in), .add_sub(add_flag), .bwd(BWD), + .result(addsub_q), .cout(cy_out), .overflow(over_flow) ); + + always @(posedge BCLK) get_psr <= (RDAA == 8'h9D) | (RDAA == 8'h90) | (RDAA == 8'h93); // PSR or US or DSR is read + always @(posedge BCLK) rd_psr <= (RDAA[1:0] == 2'b01); + always @(posedge BCLK) rd_dsr <= (RDAA[1:0] == 2'b11); + always @(posedge BCLK) get_mod <= (RDAA == 8'h9F); + + always @(OPCODE or SRC1 or SRC2 or get_psr or rd_psr or rd_dsr or get_mod or DSR or PSR or ADDR) + casex (OPCODE[3:1]) + 3'b001 : pfad_4a = SRC2 & ~SRC1; // BIC + 3'bx10 : pfad_4a = get_psr ? {({4{rd_dsr}} & DSR),16'd0,({4{rd_psr}} & PSR[11:8]),({8{~rd_dsr}} & PSR[7:0])} // MOV + : (get_mod ? {16'd0,SRC1[15:0]} : SRC1); + 3'b011 : pfad_4a = SRC2 | SRC1; // OR + 3'b101 : pfad_4a = SRC2 & SRC1; // AND + 3'b111 : pfad_4a = SRC2 ^ SRC1; // XOR + default : pfad_4a = ADDR; // ADDR, comes from ADDR_UNIT + endcase + + assign pfad_4 = (OPCODE[1:0] == 2'b00) ? addsub_q : pfad_4a; // ADD,ADDC,SUB,SUBC have extra path + + // ++++++++++++++ Format 5 Opcodes : Strings MOVS , CMPS und SKPS +++++++++++++++++++++++++++++++ + + reg [11:0] spointer,dpointer; + reg [9:0] todo; + reg [9:4] todo_reg; + reg dis_opt; + wire [31:0] diff_poi; + wire mehr,weiter,op_str,no_opt; + + assign op_str = (OPCODE[7:3] == 5'b0101_0); + + assign diff_poi = SRC2 - SRC1; // Special Case + + always @(posedge BCLK) if (op_str && OPCODE[2]) dis_opt <= (diff_poi[31:3] == 29'd0); + + // This logic is for detection if an accelerated MOVS/MOVM inside a page is possible - Backward is not possible + always @(posedge BCLK) + if (op_str) + begin + spointer <= OPCODE[2] ? SRC1[11:0] : (spointer + {8'h00,todo[3:0]}); // Source + dpointer <= OPCODE[2] ? SRC2[11:0] : (dpointer + {8'h00,todo[3:0]}); // Destination + end + + assign no_opt = OPCODE[1] | ((spointer[11:3] == 9'h1FF) & (spointer[2:0] != 3'b000)) + | kill_opt | ((dpointer[11:3] == 9'h1FF) & (dpointer[2:0] != 3'b000)) + | dis_opt; + + assign pfad_5 = SRC1 - {28'h0,todo_reg[7:4]}; + + assign mehr = (pfad_5[31:4] != 28'h0); + + always @(no_opt or BWD or mehr or pfad_5) + casex ({no_opt,BWD,mehr,pfad_5[3:0]}) + 8'b000_1xxxx : todo = 10'h388; // Byte + 8'b000_01xxx : todo = 10'h388; + 8'b000_001xx : todo = 10'h244; + 8'b000_0001x : todo = 10'h122; + 8'b000_00001 : todo = 10'h011; + // + 8'b001_1xxxx : todo = 10'h348; // Word + 8'b001_01xxx : todo = 10'h348; + 8'b001_001xx : todo = 10'h348; + 8'b001_0001x : todo = 10'h224; + 8'b001_00001 : todo = 10'h112; + // + 8'b01x_1xxxx : todo = 10'h328; // DWord + 8'b01x_01xxx : todo = 10'h328; + 8'b01x_001xx : todo = 10'h328; + 8'b01x_0001x : todo = 10'h328; + 8'b01x_00001 : todo = 10'h214; + // + 8'b100_xxxxx : todo = 10'h011; // the opcodes CMPS and SKPS work on a single element + 8'b101_xxxxx : todo = 10'h112; + 8'b11x_xxxxx : todo = 10'h214; + default : todo = 10'hxxx; + endcase + + always @(posedge BCLK) if (op_str) todo_reg <= {todo[9:8],(OPCODE[2] ? 4'd0 : todo[7:4])}; // store for next phase 51 + + assign weiter = mehr | (pfad_5[3:0] != 4'h0); + + assign STRING = {1'b0,ACB_ZERO,weiter,( op_str ? todo[9:8] : todo_reg[9:8] )}; // ACB_ZERO is delayed 1 cycle extern + + // +++++++++++++ Format 6 opcodes : ADDP + SUBP are done in DP_FPU ++++++++++++++++++++ + + wire rot,ash,lsh,eis_op; + wire [7:0] sh_count; + wire [4:0] shcode; // comes from SHIFTER + + reg [4:0] disp_reg; // for EXT/INS + reg [2:0] offs_reg; // for INSS + wire exin_op,exin_op2; + wire [4:0] shval_ei; + wire [7:0] sh_exin; + + assign rot = (OPCODE[3:0] == 4'h0); + assign ash = (OPCODE[3:0] == 4'h1); + assign lsh = (OPCODE[3:1] == 3'b010); // 5 is LSH , but 4 is Trap(UND) and is used for right-shift of Offset ! + + assign eis_op = (OPCODE == 8'h73) | (OPCODE[7] & ~OPCODE[1] & inss_op); // EXTSi | INSSi at OPCODE=80h + assign exin_op = exin_cmd & (OPCODE[7:4] == 4'h8); // identifies EXT/INS + assign exin_op2 = (exin_cmd | inss_op) & (OPCODE[7:4] == 4'h6); // identifies LSH + + always @(posedge BCLK) disp_reg <= DISP; // at EXT the path via ADDR is already used for DEST !!! + always @(posedge BCLK) if (OPCODE[7]) offs_reg <= SRC1[7:5]; // for INSS , OPCODE=80h + + // Byte for external Bit source, Double for Register + assign selbits = (bit_reg | eis_op | exin_op) ? (exin_op ? disp_reg : SRC1[4:0]) : {2'b00,BITSEL}; + + assign shval_ei = inss_op ? {2'b00,offs_reg} : (bit_reg ? SRC1[4:0] : {2'b00,SRC1[2:0]}); + assign sh_exin[4:0] = extract ? (5'd0 - shval_ei) : shval_ei; // EXT : right shift, INS : left shift + assign sh_exin[7:5] = (shval_ei == 5'd0) ? 3'b000 : {3{extract}}; // Special case : 0 has no negativ sign ! + + // LSH shift by 16 bit to right + assign sh_count = (OPCODE[3:0] == 4'h4) ? 8'hF0 : (exin_op2 ? sh_exin : SRC1[7:0]); + + assign BMCODE = (bit_op | eis_op | exin_op) ? {(eis_op | exin_op),(bit_op | exin_op),selbits} : {2'b00,shcode}; + + SHIFTER shift_inst (.MASKE(BMASKE), .ROT(rot), .ASH(ash), .LSH(lsh), .SH_DAT(SRC2), .SH_VAL(sh_count), + .MASK_SEL(shcode), .SIZE(BWD), .SH_OUT(shdat) ); + + always @(BWD or SRC2 or neg_op or dw_info) + casex ({neg_op,(dw_info | BWD[1]),BWD[0]}) // special case ADJSPi + 3'b000 : bwd_daten2 = {{24{SRC2[7]}}, SRC2[7:0]}; // Sign Extension + 3'b001 : bwd_daten2 = {{16{SRC2[15]}},SRC2[15:0]}; + 3'b1xx : bwd_daten2 = 32'h0; // is used for ABSi and NEGi + default : bwd_daten2 = SRC2; + endcase + + always @(OPCODE or SRC2 or BMASKE or addsub_q or bwd_daten1 or SRC1 or shdat or DP_OUT) + casex (OPCODE[3:0]) + 4'b001x : pfad_6 = SRC2 & ~BMASKE; // CBIT & CBITI + 4'b011x : pfad_6 = SRC2 | BMASKE; // SBIT & SBITI + 4'b1000 : pfad_6 = addsub_q; // NEG + 4'b1001 : pfad_6 = {SRC1[31:1],~SRC1[0]}; // NOT + 4'b1010 : pfad_6 = SRC1; // Special case 6A : not used normal -> op_lmr ! + 4'b1100 : pfad_6 = bwd_daten1[31] ? addsub_q : SRC1; // ABS + 4'b1101 : pfad_6 = ~SRC1; // COM + 4'b1110 : pfad_6 = SRC2 ^ BMASKE; // IBIT + 4'b1x11_: pfad_6 = DP_OUT; // ADDP + SUBP + default : pfad_6 = shdat; // Result of Barrelshifter + endcase + + // ++++++++++++++ Format 7 : MUL +++++++++++++++++++++++ + + // This Condition-Code Decoder is written twice ... see DECODER + + reg sc_bit; + wire sc_negativ,sc_zero,sc_flag,sc_larger,sc_carry_psr; + + assign sc_negativ = PSR[7]; + assign sc_zero = PSR[6]; + assign sc_flag = PSR[5]; + assign sc_larger = PSR[2]; + assign sc_carry_psr = PSR[0]; + + always @(SRC1 or sc_zero or sc_carry_psr or sc_larger or sc_negativ or sc_flag) + case (SRC1[3:0]) + 4'h0 : sc_bit = sc_zero; // EQual + 4'h1 : sc_bit = ~sc_zero; // Not Equal + 4'h2 : sc_bit = sc_carry_psr; // Carry Set + 4'h3 : sc_bit = ~sc_carry_psr; // Carry Clear + 4'h4 : sc_bit = sc_larger; // Higher + 4'h5 : sc_bit = ~sc_larger; // Lower or Same + 4'h6 : sc_bit = sc_negativ; // Greater Than + 4'h7 : sc_bit = ~sc_negativ; // Less or Equal + 4'h8 : sc_bit = sc_flag; // Flag Set + 4'h9 : sc_bit = ~sc_flag; // Flag Clear + 4'hA : sc_bit = ~sc_larger & ~sc_zero; // LOwer + 4'hB : sc_bit = sc_larger | sc_zero; // Higher or Same + 4'hC : sc_bit = ~sc_negativ & ~sc_zero; // Less Than + 4'hD : sc_bit = sc_negativ | sc_zero; // Greater or Equal + 4'hE : sc_bit = 1'b1; // True + 4'hF : sc_bit = 1'b0; // False + endcase + + reg [3:0] bytes2anz; + wire [23:0] and_src1; + wire [31:0] movxz_dat; + wire [4:0] kurz_anz; + wire [31:0] ext_sh4,ext_sh2; + + assign and_src1 = {{16{BWD[1]}},{8{BWD[0]}}} & SRC1[31:8]; // for MOVZ + + assign movxz_dat = (OPCODE[1] ^ OPCODE[0]) ? {and_src1,SRC1[7:0]} : bwd_daten1; // MOVZ.. ? + + always @(ADDR or BWD) + casex (BWD[1:0]) + 2'b00 : bytes2anz = ADDR[3:0]; + 2'b01 : bytes2anz = {1'b0,ADDR[3:1]}; + 2'b1x : bytes2anz = {2'b0,ADDR[3:2]}; + endcase + + assign kurz_anz = {1'b0,bytes2anz} + 5'h01; // count for MOVM/CMPM + + assign ext_sh4 = SRC1[7] ? {4'h0,SRC2[31:4]} : SRC2; // EXTSi + assign ext_sh2 = SRC1[6] ? {2'b0,ext_sh4[31:2]} : ext_sh4; + + always @(*) + casex (OPCODE[3:0]) + 4'b0011 : pfad_7 = (SRC1[5] ? {1'b0,ext_sh2[31:1]} : ext_sh2) & BMASKE; // EXTSi + 4'b01xx : pfad_7 = movxz_dat; // MOVXBW, MOVZBW, MOVZiD, MOVXiD + 4'b1000 : pfad_7 = MRESULT[31:0]; // MULi + 4'b1010 : pfad_7 = {27'h0,(kurz_st ? kurz_anz : {4'h0,sc_bit})}; // SCond or start of MOVM/CMPM + default : pfad_7 = DP_OUT; // DIV etc. + endcase + + // ++++++++++++++ Format 8 : multiple opcodes +++++++++++++++++++++++ + + reg chk_p1; + reg [31:0] ins_maske; + + wire [4:0] ffs_out; + wire [15:0] low_bou,upp_bou,zeiger,chk_upp,chk_low; + wire flag_up,flag_lo; + + FFS_LOGIK ffs_unit (.SRC1(SRC1), .SRC2(SRC2[4:0]), .BWD(BWD), .FLAG(ffs_flag), .DOUT(ffs_out) ); + + // CHECK : SRC1 are the Bounds + assign low_bou = BWD[0] ? SRC1[31:16] : {{8{SRC1[15]}},SRC1[15:8]}; + assign upp_bou = BWD[0] ? SRC1[15:0] : {{8{SRC1[7]}}, SRC1[7:0]}; + assign zeiger = BWD[0] ? SRC2[15:0] : {{8{SRC2[7]}}, SRC2[7:0]}; + + assign chk_upp = upp_bou - zeiger; // F=1 if upp_bou < zeiger + assign chk_low = zeiger - low_bou; // F=1 if zeiger < low_bou + + assign flag_up = (upp_bou[15] == zeiger[15]) ? chk_upp[15] : upp_bou[15]; // See NL Definition + assign flag_lo = (low_bou[15] == zeiger[15]) ? chk_low[15] : zeiger[15]; + + always @(posedge BCLK) chk_p1 <= chk_op & BWD[1]; // CHECKD needs 2 cycles to execute + + assign chk_flag = BWD[1] ? (chk_p1 ? (nl_int[1] | psr_low[5]) : nl_int[1]) : (flag_up | flag_lo); + + always @(posedge BCLK) ins_maske <= shdat; // expensive solution in terms of LEs ! + + always @(*) + casex (OPCODE[3:0]) // CVTP (81) has no OPCODE ! + 4'b000x : pfad_8 = (extract ? SRC2 : 32'hFFFF_FFFF) & BMASKE; // EXT, the other form is for INS to get the mask + 4'b0010 : pfad_8 = (SRC1 & ins_maske) | (SRC2 & ~ins_maske); // INS ins_maske[] ? SRC1[] : SRC2[] + 4'b0011 : pfad_8 = BWD[1] ? addsub_q : {16'h0,chk_low}; + 4'b0101 : pfad_8 = {24'hxx_xxxx,3'b000,ffs_out}; + default : pfad_8 = {4'hx,push_psr,SRC1[15:0]}; // Opcode x'87-x'8F is used at CXP and therefore in Exception-Processing + endcase + + // ++++++++++++++ Format 11 : Floating-Point Datapath +++++++++++++++++++++++++++++++ + + assign pfad_11 = (OPCODE[1:0] == 2'b01) ? + {((OPCODE[3:2] == 2'b11) ? 1'b0 : (SRC1[31] ^ OPCODE[2])),SRC1[30:0]} // ABSf , NEGf + MOVf + : DP_OUT; + +endmodule diff --git a/src/m32632/M32632.v b/src/m32632/M32632.v new file mode 100644 index 0000000..bf5545e --- /dev/null +++ b/src/m32632/M32632.v @@ -0,0 +1,453 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: M32632.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 7 October 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// M32632 The top level of M32632 +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module M32632( BCLK, MCLK, WRCFG, BRESET, NMI_N, INT_N, STATUS, ILO, STATSIGS, + IO_WR, IO_RD, IO_A, IO_BE, IO_DI, IO_Q, IO_READY, + ENDRAM, IC_MDONE, DC_MDONE, ENWR, WAMUX, WADDR, DRAM_Q, DWCTRL, IWCTRL, + IC_ACC, IDRAM_ADR, DC_ACC, DC_WR, DRAM_ADR, DRAM_DI, + HOLD, HLDA, FILLRAM, DMA_AA, + COP_GO, COP_OP, COP_OUT, COP_DONE, COP_IN ); + +// ++++++++++ Basic Signals +input BCLK; // Basic Clock for everything +input MCLK; // Memory Clock, used in Caches +input WRCFG; +input BRESET; +input NMI_N; +input INT_N; +output [3:0] STATUS; +output ILO; +output [7:0] STATSIGS; +// +++++++++ General Purpose Interface +output IO_WR; +output IO_RD; +output [31:0] IO_A; +output [3:0] IO_BE; +output [31:0] IO_DI; +input [31:0] IO_Q; +input IO_READY; +// +++++++++ DRAM Interface In +input ENDRAM; +input IC_MDONE; +input DC_MDONE; +input ENWR; +input WAMUX; +input [11:2] WADDR; +input [31:0] DRAM_Q; +input [2:0] DWCTRL; +input [2:0] IWCTRL; +// +++++++++ DRAM Interface Out +output IC_ACC; +output [27:0] IDRAM_ADR; +output DC_ACC; +output DC_WR; +output [27:0] DRAM_ADR; +output [35:0] DRAM_DI; +// ++++++++++ DMA Interface +input HOLD; +output HLDA; +input FILLRAM; +input [27:4] DMA_AA; +// ++++++++++ Coprocessor Interface +output COP_GO; +output [23:0] COP_OP; +output [127:0] COP_OUT; +input COP_DONE; +input [63:0] COP_IN; + +wire ACC_DONE; +wire [5:0] ACC_STAT; +wire [12:0] CFG; +wire [3:0] CINV; +wire DATA_HOLD; +wire DC_INIT; +wire Y_INIT; +wire DONE; +wire [63:0] DP_Q; +wire [3:0] IACC_STAT; +wire PROT_ERROR; +wire [2:0] GENSTAT; +wire IC_INIT; +wire IC_PREQ; +wire IC_READ; +wire [1:0] IC_SIGS; +wire IC_USER; +wire [31:12] IC_VA; +wire [3:0] ICTODC; +wire [6:0] INFO_AU; +wire [1:0] IVAR; +wire KDET; +wire [27:4] KOLLI_A; +wire [3:0] MCR; +wire [23:0] MMU_DIN; +wire [11:0] PSR; +wire PTB_SEL; +wire PTB_WR; +wire READ; +wire WRITE; +wire ZTEST; +wire RMW; +wire QWATWO; +wire [2:0] RWVAL; +wire RWVFLAG; +wire [3:0] D_IOBE; +wire D_IORDY; +wire REG_OUT; +wire [3:0] PACKET; +wire [1:0] SIZE; +wire [31:0] VADR; +wire WREN_REG; +wire LD_DIN; +wire LD_IMME; +wire WR_REG; +wire [14:0] ACC_FELD; +wire [31:0] DIN; +wire [31:0] DISP; +wire [2:0] IC_TEX; +wire [31:0] IMME_Q; +wire [1:0] LD_OUT; +wire [12:0] DETOIP; +wire [1:0] MMU_UPDATE; +wire [10:0] OPER; +wire [31:0] PC_ARCHI; +wire [31:0] PC_ICACHE; +wire [7:0] RDAA; +wire [7:0] RDAB; +wire [1:0] START; +wire [1:0] WMASKE; +wire [5:0] WRADR; +wire I_IORDY; +wire ACB_ZERO; +wire DC_ABORT; +wire SAVE_PC; +wire [31:0] IC_DIN; +wire [31:0] PC_NEW; +wire [4:0] STRING; +wire [5:0] TRAPS; +wire I_IORD; +wire D_IOWR; +wire D_IORD; +wire [31:0] D_IOA; +wire [31:0] I_IOA; +wire ENA_HK; +wire STOP_CINV; +wire KOLLISION; +wire ILO_SIG; +wire [1:0] PTE_STAT; +wire DBG_HIT; +wire [40:2] DBG_IN; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Data Cache +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +DCACHE ARMS( + .MCLK(MCLK), + .BCLK(BCLK), + .WRCFG(WRCFG), + .BRESET(BRESET), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .MDONE(DC_MDONE), + .IO_READY(D_IORDY), + .REG_OUT(REG_OUT), + .PSR_USER(INFO_AU[1]), + .WRITE(WRITE), + .READ(READ), + .ZTEST(ZTEST), + .RMW(RMW), + .QWATWO(QWATWO), + .WAMUX(WAMUX), + .ENWR(ENWR), + .IC_PREQ(IC_PREQ), + .FILLRAM(FILLRAM), +// .CFG(CFG[10:9]), + .CFG(2'b00), + .ENDRAM(ENDRAM), + .CINVAL(CINV[1:0]), + .DMA_AA(DMA_AA), + .DP_Q(DP_Q), + .DRAM_Q(DRAM_Q), + .IC_VA(IC_VA), + .ICTODC(ICTODC), + .IO_Q(IO_Q), + .IVAR(IVAR), +// .MCR_FLAGS(MCR), + .MCR_FLAGS(4'b0), + .PACKET(PACKET), + .SIZE(SIZE), + .VADR(VADR), + .WADDR(WADDR), + .WCTRL(DWCTRL), + .DRAM_ACC(DC_ACC), + .DRAM_WR(DC_WR), + .IO_RD(D_IORD), + .IO_WR(D_IOWR), + .INIT_RUN(DC_INIT), + .KDET(KDET), + .HLDA(HLDA), + .ACC_STAT(ACC_STAT), + .DP_DI(DIN), + .DRAM_A(DRAM_ADR), + .DRAM_DI(DRAM_DI), + .IACC_STAT(IACC_STAT[3:1]), + .IC_SIGS(IC_SIGS), + .IO_A(D_IOA), + .IO_BE(D_IOBE), + .IO_DI(IO_DI), + .PTE_STAT(PTE_STAT), + .DBG_HIT(DBG_HIT), + .DBG_IN(DBG_IN), + .KOLLI_A(KOLLI_A), + .MMU_DIN(MMU_DIN), + .RWVAL(RWVAL), + .RWVFLAG(RWVFLAG)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Datapath +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +DATENPFAD STOMACH( + .WREN(WREN_REG), + .BRESET(BRESET), + .BCLK(BCLK), + .IO_READY(D_IORDY), + .LD_DIN(LD_DIN), + .LD_IMME(LD_IMME), + .WR_REG(WR_REG), + .IC_USER(IC_USER), + .ACC_FELD(ACC_FELD), + .ACC_STAT(ACC_STAT), + .DIN(DIN), + .DISP(DISP), + .IC_TEX(IC_TEX), + .IMME_Q(IMME_Q), + .INFO_AU(INFO_AU), + .LD_OUT(LD_OUT), + .DETOIP(DETOIP), + .MMU_UPDATE(MMU_UPDATE), + .OPER(OPER), + .PC_ARCHI(PC_ARCHI), + .PC_ICACHE(PC_ICACHE), + .RDAA(RDAA), + .RDAB(RDAB), + .START(START), + .WMASKE(WMASKE), + .WRADR(WRADR), + .READ_OUT(READ), + .WRITE_OUT(WRITE), + .ZTEST(ZTEST), + .RMW(RMW), + .QWATWO(QWATWO), + .ACC_DONE(ACC_DONE), + .REG_OUT(REG_OUT), + .Y_INIT(Y_INIT), + .DONE(DONE), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .ACB_ZERO(ACB_ZERO), + .ABORT(DC_ABORT), + .SAVE_PC(SAVE_PC), + .CFG(CFG), + .CINV(CINV), + .DP_Q(DP_Q), + .IVAR(IVAR), + .MCR(MCR), + .PACKET(PACKET), + .PC_NEW(PC_NEW), + .PSR(PSR), + .SIZE(SIZE), + .STRING(STRING), + .TRAPS(TRAPS), + .VADR(VADR), + .RWVFLAG(RWVFLAG), + .DBG_HIT(DBG_HIT), + .DBG_IN(DBG_IN), + .COP_DONE(COP_DONE), + .COP_OP(COP_OP), + .COP_IN(COP_IN), + .COP_GO(COP_GO), + .COP_OUT(COP_OUT)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Instruction Cache +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +ICACHE LEGS( + .MCLK(MCLK), + .BCLK(BCLK), + .BRESET(BRESET), + .PTB_WR(PTB_WR), + .PTB_SEL(PTB_SEL), + .MDONE(IC_MDONE), + .IO_READY(I_IORDY), + .READ_I(IC_READ), + .PSR_USER(IC_USER), + .DATA_HOLD(DATA_HOLD), + .DRAM_WR(DC_WR), + .KDET(KDET), + .HOLD(HOLD), +// .CFG(CFG[12:11]), + .CFG(2'b00), + .ENDRAM(ENDRAM), + .DRAM_Q(DRAM_Q), + .CINVAL(CINV[3:2]), + .IC_SIGS(IC_SIGS), + .IO_Q(IO_Q), + .IVAR(IVAR), + .KOLLI_A(KOLLI_A), +// .MCR_FLAGS(MCR), + .MCR_FLAGS(4'b0), + .MMU_DIN(MMU_DIN), + .VADR(PC_ICACHE), + .WADDR(WADDR), + .WCTRL(IWCTRL), + .DRAM_ACC(IC_ACC), + .IO_RD(I_IORD), + .INIT_RUN(IC_INIT), + .PROT_ERROR(PROT_ERROR), + .ACC_OK(IACC_STAT[0]), + .IC_PREQ(IC_PREQ), + .KOLLISION(KOLLISION), + .DRAM_A(IDRAM_ADR), + .IC_DQ(IC_DIN), + .IC_VA(IC_VA), + .ICTODC(ICTODC), + .ENA_HK(ENA_HK), + .STOP_CINV(STOP_CINV), + .IO_A(I_IOA)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Control Unit +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +STEUERUNG BRAIN( + .BCLK(BCLK), + .BRESET(BRESET), + .DC_ACC_DONE(ACC_DONE), + .ACB_ZERO(ACB_ZERO), + .DONE(DONE), + .NMI_N(NMI_N), + .INT_N(INT_N), + .DC_ABORT(DC_ABORT), + .IC_INIT(IC_INIT), + .DC_INIT(DC_INIT), + .Y_INIT(Y_INIT), + .SAVE_PC(SAVE_PC), + .CFG(CFG[8:0]), + .IACC_STAT(IACC_STAT), + .PROT_ERROR(PROT_ERROR), + .IC_DIN(IC_DIN), + .PC_NEW(PC_NEW), + .PSR(PSR), + .STRING(STRING), + .TRAPS(TRAPS), + .IC_READ(IC_READ), + .DATA_HOLD(DATA_HOLD), + .LD_DIN(LD_DIN), + .LD_IMME(LD_IMME), + .WREN(WREN_REG), + .WR_REG(WR_REG), + .GENSTAT(GENSTAT), + .IC_USER(IC_USER), + .ACC_FELD(ACC_FELD), + .DISP(DISP), + .IC_TEX(IC_TEX), + .IMME_Q(IMME_Q), + .INFO_AU(INFO_AU), + .LD_OUT(LD_OUT), + .DETOIP(DETOIP), + .MMU_UPDATE(MMU_UPDATE), + .OPER(OPER), + .PC_ARCHI(PC_ARCHI), + .PC_ICACHE(PC_ICACHE), + .RDAA(RDAA), + .RDAB(RDAB), + .START(START), + .WMASKE(WMASKE), + .WRADR(WRADR), + .ENA_HK(ENA_HK), + .STOP_CINV(STOP_CINV), + .COP_OP(COP_OP), + .ILO(ILO_SIG), + .RWVAL(RWVAL)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Input/Output Interface +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +IO_SWITCH ISWITCH( + .I_IORD(I_IORD), + .D_IOWR(D_IOWR), + .IO_READY(IO_READY), + .D_IORD(D_IORD), + .D_IOBE(D_IOBE), + .BRESET(BRESET), + .BCLK(BCLK), + .GENSTAT(GENSTAT), + .D_IOA(D_IOA), + .I_IOA(I_IOA), + .D_IORDY(D_IORDY), + .I_IORDY(I_IORDY), + .IO_RD(IO_RD), + .IO_WR(IO_WR), + .IO_BE(IO_BE), + .ILO_SIG(ILO_SIG), + .ILO(ILO), + .IO_A(IO_A), + .DCWACC({DC_WR,DC_ACC}), + .STATUS(STATUS)); + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// The Statistic Signal Generator +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +MAKE_STAT MKSTAT( + .BCLK(BCLK), + .READ(READ), + .DACC_OK(ACC_STAT[0]), + .KOLLISION(KOLLISION), + .DC_ACC(DC_ACC), + .DPTE_ACC(PTE_STAT[0]), + .DC_MDONE(DC_MDONE), + .DRAM_WR(DC_WR), + .IC_READ(IC_READ), + .IACC_OK(IACC_STAT[0]), + .IC_ACC(IC_ACC), + .IPTE_ACC(PTE_STAT[1]), + .IC_MDONE(IC_MDONE), + .DATA_HOLD(DATA_HOLD), + .STATSIGS(STATSIGS)); + +endmodule diff --git a/src/m32632/REGISTERS.v b/src/m32632/REGISTERS.v new file mode 100644 index 0000000..c4c3880 --- /dev/null +++ b/src/m32632/REGISTERS.v @@ -0,0 +1,324 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: REGISTERS.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. CONFIG_REGS Configuration and Debug Registers +// 2. FP_STAT_REG Floating Point Status Register +// 3. REGISTER General Purpose Registers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. CONFIG_REGS Configuration and Debug Registers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module CONFIG_REGS ( BCLK, BRESET, WREN, LD_OUT, OPCODE, SRC1, WRADR, PC_ARCHI, USER, PCMATCH, DBG_HIT, READ, + CFG, MCR, PTB_WR, PTB_SEL, IVAR, CINV, Y_INIT, DSR, DBG_TRAPS, DBG_IN ); + + input BCLK,BRESET; + input WREN,LD_OUT; + input [7:0] OPCODE; + input [31:0] SRC1; + input [5:0] WRADR; + input [31:0] PC_ARCHI; + input USER; + input PCMATCH; + input DBG_HIT; + input READ; + + output [12:0] CFG; + output [3:0] MCR; + output PTB_WR; + output PTB_SEL; + output [1:0] IVAR; + output [3:0] CINV; + output Y_INIT; + output [3:0] DSR; + output [2:0] DBG_TRAPS; + output [40:2] DBG_IN; + + reg [3:0] MCR; + reg [12:0] CFG; + reg [1:0] old_cfg; + reg PTB_WR,PTB_SEL; + reg ivarreg; + reg [1:0] ci_all,ci_line; + reg check_y; + + wire ld_cfg,ld_mcr,do_cinv; + wire init_ic,init_dc; + wire op_ok; + + assign op_ok = (OPCODE == 8'h6A); // Special Opcode - for security reason + + assign ld_cfg = op_ok & (WRADR == 6'h1C) & WREN; + assign ld_mcr = op_ok & (WRADR == 6'd9) & WREN; + assign do_cinv = op_ok & (WRADR[5:4] == 2'b11) & WREN; + + // PF is not implemented + always @(posedge BCLK or negedge BRESET) + if (!BRESET) CFG <= 13'h0; + else if (ld_cfg) CFG <= SRC1[12:0]; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) MCR <= 4'h0; + else if (ld_mcr) MCR <= SRC1[3:0]; + + always @(posedge BCLK) ivarreg <= op_ok & (WRADR[5:1] == 5'd7) & WREN; // IVAR0/1 = Reg. Nr. 14/15 + assign IVAR = {ivarreg,PTB_SEL}; + + always @(posedge BCLK) PTB_WR <= op_ok & (WRADR[5:1] == 5'd6) & WREN; // PTB0/1 = Reg. Nr. 12/13 + always @(posedge BCLK) PTB_SEL <= WRADR[0]; + + // The Cache content will be invalid if the Enable-Bit is set to 0 + always @(posedge BCLK) old_cfg <= {CFG[11],CFG[9]}; + + // Cache Invalidate : the Flags are coming out of the Short-field which is otherwise used for Register selection + always @(posedge BCLK) ci_all <= do_cinv & WRADR[2] ? WRADR[1:0] : 2'b0; // clear all + always @(posedge BCLK) ci_line <= do_cinv & ~WRADR[2] ? WRADR[1:0] : 2'b0; // clear cache line + + assign init_ic = old_cfg[1] & (~CFG[11] | ci_all[1]); + assign init_dc = old_cfg[0] & (~CFG[9] | ci_all[0]); + + assign CINV = {init_ic,ci_line[1],init_dc,ci_line[0]}; + + // Y_INIT is neccessary if nothing has changed and therefore no DC/IC_INIT is generated + always @(posedge BCLK) check_y <= ld_cfg | do_cinv; + assign Y_INIT = check_y & ~init_ic & ~init_dc; // goes to register "old_init" + + // +++++++++++++ DEBUG Unit +++++++++++++++ + + reg [3:0] DSR; + reg [12:0] dcr; + reg [31:0] bpc; + reg [31:2] car; + + wire op_dbg,ld_dcr,ld_bpc,ld_dsr,ld_car; + wire enable; + + assign op_dbg = (OPCODE == 8'h76); + + assign ld_dcr = op_dbg & (WRADR == 6'h11) & WREN; + assign ld_bpc = op_dbg & (WRADR == 6'h12) & WREN; + assign ld_dsr = op_dbg & (WRADR == 6'h13) & WREN; + assign ld_car = op_dbg & (WRADR == 6'h14) & WREN; + + assign enable = dcr[12] & (USER ? dcr[10] : dcr[11]); // DEN & (USER ? UD : SD) + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) dcr <= 13'd0; + else if (ld_dcr) dcr <= {SRC1[23:19],SRC1[7:0]}; + + always @(posedge BCLK) if (ld_bpc) bpc <= SRC1; + always @(posedge BCLK) if (ld_car) car <= SRC1[31:2]; + + // DEN SD DEN UD CAE CRD CAE CWR VNP/CBE CAR + assign DBG_IN = {(dcr[12] & dcr[11]),(dcr[12] & dcr[10]),(dcr[7] & dcr[6]),(dcr[7] & dcr[5]),dcr[4:0],car}; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) DSR <= 4'd0; + else + if (ld_dsr) DSR <= SRC1[31:28]; + else + begin + DSR[3] <= DBG_HIT ? READ : DSR[3]; + DSR[2] <= DSR[2] | PCMATCH; + DSR[1] <= DSR[1]; + DSR[0] <= DSR[0] | DBG_HIT; + end + + assign DBG_TRAPS[0] = enable & dcr[9] & (PC_ARCHI == bpc); // dcr[9]=PCE + assign DBG_TRAPS[1] = DBG_HIT; // Compare Adress Hit + assign DBG_TRAPS[2] = dcr[8]; // TR, Trap enable + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. FP_STAT_REG Floating Point Status Register +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module FP_STAT_REG ( BCLK, BRESET, LFSR, UP_SP, UP_DP, TT_SP, TT_DP, WREN, WRADR, DIN, FSR, TWREN, FPU_TRAP, SAVE_PC); + + input BCLK; + input BRESET; + input LFSR; // Load by LFSR opcode + input UP_SP,UP_DP; // update if calculation operation + input [4:0] TT_SP,TT_DP; + input WREN; // for RMB and LFSR + input [5:4] WRADR; + input [16:0] DIN; // Data for LFSR opcode + + output [31:0] FSR; + output TWREN; + output reg FPU_TRAP; + output SAVE_PC; + + reg [4:3] trap_d; + reg update_d; + reg set_rm_d; + reg [10:0] set_bits; + reg [4:0] flags; + reg rm_bit; + + wire load_fsr; + wire update,update_i; + wire [4:0] trap; + wire uflag,iflag,rmflag; + + assign load_fsr = LFSR & WREN; + + assign trap = UP_SP ? TT_SP : TT_DP; + + // This signal suppresses write into registers if FPU Trap, timing critical signal ! + assign TWREN = ~((UP_SP & (TT_SP[2:0] != 3'b0)) | (UP_DP & (TT_DP[2:0] != 3'b0))); + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) FPU_TRAP <= 1'b0; + else FPU_TRAP <= ~FPU_TRAP & ~TWREN; // one pulse of one cycle informs the Opcode Decoder + + assign update_i = (UP_SP | UP_DP) & ~FPU_TRAP; // unfortunately one FPU opcode may follow ! + always @(posedge BCLK) update_d <= update_i; + always @(posedge BCLK) trap_d <= trap[4:3]; + always @(posedge BCLK) set_rm_d <= WREN & (WRADR == 2'b10); + assign update = update_d & ~FPU_TRAP; + + // The Flags are set and stay "1" + assign iflag = (update & trap_d[4]) | flags[4]; // Inexact Result + assign uflag = (update & trap_d[3]) | flags[3]; // Underflow + assign rmflag = (set_rm_d & ~FPU_TRAP) | rm_bit; // Register Modify + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) flags[4:3] <= 2'b0; // Inexact = Bit6, Underflow = Bit4 + else + begin + if (load_fsr) flags[4:3] <= {DIN[6],DIN[4]}; + else + if (update) flags[4:3] <= {iflag,uflag}; + end + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) flags[2:0] <= 3'b0; // TT Field = Bit2-0 + else + begin + if (load_fsr) flags[2:0] <= DIN[2:0]; + else + if (update_i) flags[2:0] <= trap[2:0]; + end + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) rm_bit <= 1'b0; // Register Modify Bit + else + begin + if (load_fsr) rm_bit <= DIN[16]; + else + if (set_rm_d & ~FPU_TRAP) rm_bit <= 1'b1; // in case of TRAP there is no writing to Register + end + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) set_bits <= 11'b0; // all other Bits + else + if (load_fsr) set_bits <= {DIN[15:7],DIN[5],DIN[3]}; + + assign FSR = {15'h0,rmflag,set_bits[10:2],iflag,set_bits[1],uflag,set_bits[0],flags[2:0]}; + + assign SAVE_PC = (UP_SP | UP_DP) & ~FPU_TRAP; // Store the correct PC for FPU Trap + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. REGISTER General Purpose Registers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module REGISTER( BCLK, ENWR, DOWR, BYDIN, DIN, RADR, WADR, WMASKE, DOUT, SELI ); + +input BCLK; +input DOWR,ENWR; +input [31:0] BYDIN,DIN; +input [7:0] RADR; +input [5:0] WADR; +input [1:0] WMASKE; + +output [31:0] DOUT; +output reg SELI; + +reg [2:0] MX; + +wire [3:0] BE; +wire eq_rw; + +// +++++++++++++++++++ Memories ++++++++++++++++++++ + +reg [7:0] REGFILE_D [0:63]; +reg [7:0] REGFILE_C [0:63]; +reg [7:0] REGFILE_B [0:63]; +reg [7:0] REGFILE_A [0:63]; +reg [31:0] RF; + +assign BE = {WMASKE[1],WMASKE[1],(WMASKE[1] | WMASKE[0]),1'b1}; + +assign eq_rw = ENWR & (RADR[5:0] == WADR); + +always @(posedge BCLK) if (RADR[7]) MX[2:0] <= BE[2:0] & {{3{eq_rw}}}; + +always @(posedge BCLK) if (RADR[7]) SELI <= RADR[6]; + +assign DOUT[31:16] = MX[2] ? BYDIN[31:16] : RF[31:16]; +assign DOUT[15:8] = MX[1] ? BYDIN[15:8] : RF[15:8]; +assign DOUT[7:0] = MX[0] ? BYDIN[7:0] : RF[7:0]; + +// ++++++++++++++++ Register File 64 * 32 Bits ++++++++++++ + +always @(posedge BCLK) + if (RADR[7]) + begin + RF[31:24] <= REGFILE_D[RADR[5:0]]; + RF[23:16] <= REGFILE_C[RADR[5:0]]; + RF[15:8] <= REGFILE_B[RADR[5:0]]; + RF[7:0] <= REGFILE_A[RADR[5:0]]; + end + +always @(posedge BCLK) + if (DOWR) + begin + if (BE[3]) REGFILE_D[WADR] <= DIN[31:24]; + if (BE[2]) REGFILE_C[WADR] <= DIN[23:16]; + if (BE[1]) REGFILE_B[WADR] <= DIN[15:8]; + if (BE[0]) REGFILE_A[WADR] <= DIN[7:0]; + end + +endmodule + diff --git a/src/m32632/SP_FPU.v b/src/m32632/SP_FPU.v new file mode 100644 index 0000000..67ba6da --- /dev/null +++ b/src/m32632/SP_FPU.v @@ -0,0 +1,472 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: SP_FPU.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. ADDSUB Adder and Subtractor for 36 bit +// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter +// 3. SFPU_MUL Single Precision Floating Point Multiplier +// 4. SP_FPU Top Level of Single Precision Floating Point Unit +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. ADDSUB Adder and Subtractor for 36 bit +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ADDSUB (dataa, datab, add_sub, result); + + input [35:0] dataa,datab; + input add_sub; // 1 = Addition , 0 = Subtraction + output [35:0] result; + + assign result = dataa + (add_sub ? datab : ~datab) + {35'd0,~add_sub}; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. SFPU_ADDSUB Single Precision Floating Point Adder/Subtractor and Converter +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SFPU_ADDSUB ( SRC1, SRC2, NZEXP, BWD, SELECT, OUT, IOUT, CMPRES ); + + input [31:0] SRC1,SRC2; // Input data + input [2:1] NZEXP; + input [1:0] BWD; // size of integer + input [3:0] SELECT; + + output [36:0] OUT; // the result + output [31:0] IOUT; // result of ROUNDFi/TRUNCFi/FLOORFi + output [1:0] CMPRES; + + // ++++++++++++++++++++++++++++++++++ + // MOViF : 1. step + + reg [31:8] movdat; + wire [31:0] movif; + + always @(BWD or SRC1) + casex({BWD,SRC1[15],SRC1[7]}) + 4'b00x0 : movdat = 24'h0000_00; // Byte + 4'b00x1 : movdat = 24'hFFFF_FF; + 4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word + 4'b011x : movdat = {16'hFFFF,SRC1[15:8]}; + default : movdat = SRC1[31:8]; // Double + endcase + + assign movif = movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]}; + // -2^31 is kept + + // ROUNDFi/TRUNCFi/FLOORFi : 1. step + + reg ovflag,ovflag2; + wire [8:0] rexdiff,rexo; + wire rovfl,minint; + wire ganzklein; // Flag for 0 + + assign rexdiff = 9'h09D - {1'b0,SRC1[30:23]}; // 4..0 is the right shift value + assign rovfl = (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint; + assign ganzklein = (~rexdiff[8] & (rexdiff[7:5] != 3'b000)); // 0 is implicit via SRC1[30:23]=0 + + // Detection of Overflow + assign rexo = ({1'b0,SRC1[30:23]} - {8'h3F,~BWD[1]}); // subtract B/W = 7F , D = 7E + + always @(BWD or rexo) + casex (BWD) + 2'b00 : ovflag = (~rexo[8] & (rexo[7:3] != 5'h0)); // Exponent 0..7 because of -128.4 => -128 + 2'b01 : ovflag = (~rexo[8] & (rexo[7:4] != 4'h0)); // Exponent 0..15 because of -128.4 => -128 + default : ovflag = (~rexo[8] & (rexo[7:5] != 3'h0)); // Exponent only 0..30 + endcase + + assign minint = (SRC1 == 32'hCF00_0000) & BWD[1]; // detection of -2^31 + + // ++++++++++++++++++++++++++++++++++ + // ADD/SUB : 1. step : which operand ist bigger ? if required exchange + // SUB/CMP : SRC2 - SRC1 + + wire [8:0] exdiff; + wire [23:0] madiff; + wire switch,sign,sign1,sign2; + wire variante; + wire vorz,addflag; + wire [35:0] result_sw,result_nosw; + wire [24:0] value1,value2; + + wire [35:0] result; + + assign exdiff = {1'b0,SRC2[30:23]} - {1'b0,SRC1[30:23]}; // Difference of Exponents + assign madiff = {1'b0,SRC2[22:0]} - {1'b0,SRC1[22:0]}; // Difference of Mantissas + + // if exdiff = 0 the shifter to the right is not needed ! + assign variante = (exdiff[8:1] == 8'h00) | (exdiff == 9'h1FF) | SELECT[1]; // MUX at the end, ROUND/TRUNC/MOViF uses case 1 + +// ++++++++++++++++++++++++++ 1. case works on MOViF +++++++++++++++++++++++++++++++++++++++ + + assign switch = exdiff[8] | ((exdiff[7:0] == 8'h0) & madiff[23]); // exchange ? + + assign value1 = exdiff[0] ? {1'b0,NZEXP[1],SRC1[22:0]} : {NZEXP[1],SRC1[22:0],1'b0}; + assign value2 = exdiff[0] ? {1'b0,NZEXP[2],SRC2[22:0]} : {NZEXP[2],SRC2[22:0],1'b0}; + + // The Subtraction needs 3 Guard-Bits after LSB for rounding ! 36 Bit wide + // 1 + ADDSUB addsub_nosw (.dataa({1'b0,SRC2[30:23],NZEXP[2],SRC2[22:0],3'b000}), + .datab({9'h0,value1,2'b0}), .add_sub(addflag), + .result(result_nosw) ); + + ADDSUB addsub_sw (.dataa({1'b0,SRC1[30:23],NZEXP[1],SRC1[22:0],3'b000}), + .datab({9'h0,value2,2'b0}), .add_sub(addflag), + .result(result_sw) ); + + assign result = switch ? result_sw : result_nosw; + + // SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1 + // 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0 + // 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2 + // (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2 + // (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8 + // 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1 + // 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8 + // (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8 + // (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2 + + assign sign1 = SRC1[31]; + assign sign2 = SRC2[31]; + + assign vorz = switch ? (SELECT[0] ^ sign1) : sign2; + assign addflag = ~(SELECT[0] ^ (sign1 ^ sign2)); + + // CMPF : 1. step : what happend if Invalid Operand occurs - no Flag update ! + + assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // see table above : N-Bit=1 if SRC1 > SRC2 + assign CMPRES[0] = (SRC1 == SRC2) | (~NZEXP[2] & ~NZEXP[1]); // Z-Bit : SRC1=SRC2, +0.0 = -0.0 + + // ++++++++++++++++++++++++++++++++++ + // ADD/SUB : 3. step : prepare of Barrelshifter Left + + wire [31:0] blshift; + wire [9:0] shiftl; + wire shift_16; + wire [33:0] add_q; + wire [31:0] muxsrc2; + wire [1:0] inex; + + assign blshift = SELECT[1] ? movif : {result[26:0],5'h00}; // Feeding of MOViF + + assign shiftl = SELECT[1] ? 10'h09E : {1'b0,result[35:27]}; // MOViF + + assign shift_16 = (blshift[31:16] == 16'h0000); + + // In case of ADD the result bypasses the Barrelshifter left + assign add_q = (muxsrc2[24] != result[27]) ? {result[35:3],(result[2:0] != 3'b000)} + : {result[35:27],result[25:2],(result[1:0] != 2'b00)} ; + + // ++++++++++++++++++++++++++++++++++ + // ADD/SUB : 4. step : Barrelshifter left for SUB and MOViF : + + wire shift_8,shift_4,shift_2,shift_1,zero; + wire [1:0] lsb_bl; + wire [31:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte; + wire [9:0] expol; + wire [36:0] out_v1; + + assign blshifta = shift_16 ? {blshift[15:0],16'h0000} : blshift; + assign shift_8 = (blshifta[31:24] == 8'h00); + assign blshiftb = shift_8 ? {blshifta[23:0],8'h00} : blshifta; + assign shift_4 = (blshiftb[31:28] == 4'h0); + assign blshiftc = shift_4 ? {blshiftb[27:0],4'h0} : blshiftb; + assign shift_2 = (blshiftc[31:30] == 2'b00); + assign blshiftd = shift_2 ? {blshiftc[29:0],2'b00} : blshiftc; + assign shift_1 = ~blshiftd[31]; + assign blshifte = shift_1 ? {blshiftd[30:0],1'b0} : blshiftd; + + // Overflow at ROUNDFi/TRUNCFi/FLOORFi via overflow in exponent shown, SELECT[1] is then 1 ! + assign expol = (shiftl - {5'h00,shift_16,shift_8,shift_4,shift_2,shift_1}) | {1'b0,rovfl,8'h00}; + + // Inexact at ROUNDFi/TRUNCFi/FLOORFi : evaluation for all one level higher + assign lsb_bl = (SELECT[1:0] == 2'b11) ? inex : {blshifte[7],(blshifte[6:0] != 7'h00)}; + + assign zero = (~SELECT[1] & ~NZEXP[2] & ~NZEXP[1]) + | ((blshift == 32'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10))); + + assign sign = SELECT[1] ? movdat[31] : vorz; + + assign out_v1 = (addflag & ~SELECT[1]) ? {zero,sign,1'b0,add_q} + : {zero,sign,expol,blshifte[30:8],lsb_bl}; + +// +++++++++++++++++++++++++ 2. case works on ROUND/TRUNC/FLOOR ++++++++++++++++++++++++++++++++++ + + wire vswitch; + wire [4:0] shift1,shift2; + wire [8:0] exdiff12; + wire [23:0] muxsrc1; + wire [32:9] pipe1; // numbering special for Right Shifter + wire [4:0] shift; + +// the difference between SRC1 and SRC2 is bigger/equal 4:1 => no Barrelshifter after ADDSUB neccessary + + assign vswitch = exdiff[8]; // exchange ? + + assign shift1 = (exdiff[7:5] != 3'h0) ? 5'h1F : exdiff[4:0]; + assign exdiff12 = {1'b0,SRC1[30:23]} - {1'b0,SRC2[30:23]}; // caclulate already + assign shift2 = (exdiff12[7:5] != 3'h0) ? 5'h1F : exdiff12[4:0]; + + assign muxsrc2 = vswitch ? {SRC1[30:23],1'b1,SRC1[22:0]} : {SRC2[30:23],1'b1,SRC2[22:0]}; // Including exponent + assign muxsrc1 = vswitch ? {NZEXP[2],SRC2[22:0]} : {NZEXP[1],SRC1[22:0]}; + + assign pipe1 = SELECT[1] ? (ganzklein ? 24'h0 : {NZEXP[1],SRC1[22:0]}) : muxsrc1; // Feeding in R.T.F. + + assign shift = SELECT[1] ? rexdiff[4:0] : (vswitch ? shift2 : shift1); + + // ++++++++++++++++++++++++++++++++++ + // ADD/SUB + ROUND/TRUNC/FLOOR : 2. step : Barrelshifter to right --> + + wire [32:0] brshifta,brshiftb,brshiftc,brshiftd; + wire [32:0] brshifte; // last stage + + // 33322222222221111111111 + // 2109876543210987654321098765432-10 + // 1VVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 Bit for rounding + + assign brshifta = shift[4] ? {16'h0,pipe1[32:17], (pipe1[16:9] != 8'h00)} : {pipe1,9'h0}; + assign brshiftb = shift[3] ? { 8'h0,brshifta[32:9],(brshifta[8:0] != 9'h000)} : brshifta; + assign brshiftc = shift[2] ? { 4'h0,brshiftb[32:5],(brshiftb[4:0] != 5'h00)} : brshiftb; + assign brshiftd = shift[1] ? { 2'h0,brshiftc[32:3],(brshiftc[2:0] != 3'h0)} : brshiftc; + assign brshifte = shift[0] ? { 1'b0,brshiftd[32:2],(brshiftd[1:0] != 2'h0)} : brshiftd; + + // ++++++++++++++++++++++++++++++++++ + // ROUNDFi/TRUNCFi/FLOORFi : 3. step : round to integer + + reg car_ry; + wire [30:0] compl; + wire [31:0] iadder; + + assign inex = brshifte[1:0]; // Inexact-Flag-Data via multiplexer at the end + + always @(SELECT or sign1 or brshifte or inex or ganzklein) + casex (SELECT[3:2]) + 2'b00 : car_ry = sign1 ^ ((brshifte[2:0] == 3'b110) | (inex == 2'b11)); // ROUNDLi + 2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers round to "-infinity" + default : car_ry = sign1; // TRUNCLi , simple cut + endcase + + assign compl = sign1 ? ~brshifte[32:2] : brshifte[32:2]; + + assign iadder = {sign1,compl} + {31'h0,car_ry}; + + assign IOUT = minint ? 32'h8000_0000 : iadder; + + always @(iadder or BWD or sign1) // special overflow detection i.e. -129 bis -255 bei Byte + casex (BWD) // or 127.9 -> 128 = Fehler ! + 2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte + 2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word + default : ovflag2 = 1'b0; + endcase + + // ++++++++++++++++++++++++++++++++++ + // only ADD/SUB : 3. step : Add or Subtract + // the modul ADDSUB integrates the carry from the mantissa : 35 Bit + + wire lsb; + wire [35:0] vresult; + wire [7:0] eminus1; + wire [33:0] vadd_q,vsub_q; + wire vzero; + wire [36:0] out_v0; + + assign lsb = (brshifte[6:0] != 7'h00); + + // Adder-Definition : "0"(8 Bit Exponent)"1"(23 Bit Mantissa)"000" + + ADDSUB addsub_v (.dataa({1'b0,muxsrc2,3'b000}), + .datab({9'h0,brshifte[32:7],lsb}), .add_sub(addflag), + .result(vresult) ); + + assign eminus1 = muxsrc2[31:24] - 8'h01; // a greater Underflow can not exist, because minimal Exponent = 0..01 + + // Case ADD : Bit 23 : LSB of exponent + assign vadd_q = (muxsrc2[24] != vresult[27]) ? {vresult[35:3],(vresult[2:0] != 3'b000)} + : {vresult[35:27],vresult[25:2],(vresult[1:0] != 2'b00)} ; + + // Case SUB : Bit 26 : "hidden" MSB of mantissa + assign vsub_q = vresult[26] ? {vresult[35:27], vresult[25:2],(vresult[1:0] != 2'b00)} // like the vadd_q "0" case + : {vresult[35],eminus1,vresult[24:0]} ; + + // SELECT[1] has here no meaning + assign vzero = (vresult[26:0] == 27'h0) & ~addflag; // only if "-" can be the result 0 + + assign out_v0 = addflag ? {vzero,vorz,1'b0,vadd_q} + : {vzero,vorz,1'b0,vsub_q} ; + + assign OUT = variante ? out_v1 : out_v0; // Last multiplexer + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. SFPU_MUL Single Precision Floating Point Multiplier +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SFPU_MUL ( SRC1, SRC2, MRESULT, NZEXP, OUT); + + input [31:0] SRC1,SRC2; // only exponent of input data used + input [47:0] MRESULT; + input [2:1] NZEXP; // Flags of input data + + output [36:0] OUT; // The result + + wire [9:0] exponent,expoh,expol; + wire [1:0] restlow,resthigh; + wire zero,sign,orlow; + + assign zero = ~NZEXP[2] | ~NZEXP[1]; // one of both NULL -> NULL is the result + assign sign = (SRC1[31] ^ SRC2[31]) & ~zero; + assign orlow = (MRESULT[21:0] != 22'b0); + + assign restlow = {MRESULT[22],orlow}; + assign resthigh = {MRESULT[23],(MRESULT[22] | orlow)}; + + assign exponent = {2'b00,SRC1[30:23]} + {2'b00,SRC2[30:23]}; + assign expoh = exponent - 10'h07E; + assign expol = exponent - 10'h07F; // for MSB if MRESULT=0 + + assign OUT = MRESULT[47] ? {zero,sign,expoh,MRESULT[46:24],resthigh} + : {zero,sign,expol,MRESULT[45:23],restlow}; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. SP_FPU Top Level of Single Precision Floating Point Unit +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module SP_FPU (BCLK, OPCODE, SRC1, SRC2, FSR, MRESULT, BWD, FL, FP_OUT, I_OUT, TT_SP, SP_CMP, SP_MUX, LD_FSR, UP_SP); + + input BCLK; // is not used ! + input [7:0] OPCODE; + input [31:0] SRC1,SRC2; // Input data + input [8:3] FSR; // Floating Point Status Register + input [47:0] MRESULT; // Multiplier result + input [1:0] BWD; // Size of integer + input FL; + + output [31:0] FP_OUT,I_OUT; // The results + output [4:0] TT_SP; // Trap-Type + output [2:0] SP_CMP; // CMPF result + output SP_MUX,LD_FSR,UP_SP; + + reg [2:0] tt; + reg [3:0] select; + reg car_ry; + + wire [36:0] mulout,addout,fpout; + wire [2:1] nzexp; + wire [34:2] rund; // Indexnumbers like xxxout + wire overflow,underflow,inexact; + wire op_cmp; + wire nan,nan_1,nan_2; + + // Control of datapath + + always @(OPCODE) + casex (OPCODE) + 8'b1011_0000 : select = 4'b1000; // 0 0 0 : ADDF Shifter are reused + 8'b1011_0100 : select = 4'b1001; // 0 0 1 : SUBF + 8'b1001_000x : select = 4'b1010; // 0 1 0 : MOViF + 8'b1001_100x : select = 4'b1011; // 0 1 1 : ROUNDFi + 8'b1001_101x : select = 4'b1011; // 0 1 1 : TRUNCFi + 8'b1001_111x : select = 4'b1011; // 0 1 1 : FLOORFi + 8'b1011_0010 : select = 4'b1001; // 0 0 1 : CMPF + 8'b1011_1100 : select = 4'b1100; // 1 x x : MULF + default : select = 4'b0; + endcase + + assign SP_MUX = select[3] & (select[1:0] != 2'b11) & FL; // Output multiplexer + + assign LD_FSR = (OPCODE[7:4] == 4'h9) & (OPCODE[3:1] == 3'b001); // LFSR does only Double (according datasheet NS32016) + assign UP_SP = select[3] & FL; // All FPU opcodes of SP_FPU + assign op_cmp = (OPCODE == 8'hB2) & FL; + + // SRCFLAGS + + assign nzexp[2] = (SRC2[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN ! + assign nzexp[1] = (SRC1[30:23] != 8'd0); // only exponent 0 ,denormalized Number => NAN ! + assign nan_2 = (SRC2[30:23] == 8'hFF) | (~nzexp[2] & (SRC2[22:0] != 23'd0)); // NAN + assign nan_1 = (SRC1[30:23] == 8'hFF) | (~nzexp[1] & (SRC1[22:0] != 23'd0)); // NAN + + assign nan = (select[1:0] == 2'b11) ? nan_1 : (~select[1] & (nan_2 | nan_1)); + + // 001 : ADDF,... + 011 : CMPF + SFPU_ADDSUB IADDSUB ( .SRC1(SRC1), .SRC2(SRC2), .NZEXP(nzexp), .BWD(BWD), + .SELECT({OPCODE[2:1],select[1:0]}), .OUT(addout), .IOUT(I_OUT), .CMPRES(SP_CMP[1:0]) ); + + // 100 : MULF + SFPU_MUL IMUL ( .SRC1(SRC1), .SRC2(SRC2), .MRESULT(MRESULT), .OUT(mulout), .NZEXP(nzexp) ); + + // FP - Pfad : selection of result and rounding : + + assign fpout = (OPCODE[5] & OPCODE[3]) ? mulout : addout; + + always @(FSR or fpout) // calculate Carry according rounding mode, fpout[35] = sign bit + casex (FSR[8:7]) + 2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest + 2'b10 : car_ry = ~fpout[35] & (fpout[1:0] != 2'b00); // round to positiv infinity + 2'b11 : car_ry = fpout[35] & (fpout[1:0] != 2'b00); // round to negativ infinity + default : car_ry = 1'b0; // round to zero + endcase + + assign rund = {fpout[34:2]} + {32'h0,car_ry}; + + // Detection of Overflow, Underflow and Inexact : epxonent is [34:25] = 10 Bits + assign overflow = ~rund[34] & (rund[33] | (rund[32:25] == 8'hFF)); + assign underflow = (rund[34] | (rund[33:25] == 9'h0)) & ~fpout[36]; // Zero-Flag + assign inexact = (fpout[1:0] != 2'b00); + + // CMPF can have no other error except NAN + always @(nan or op_cmp or overflow or underflow or inexact or FSR) + casex ({nan,op_cmp,overflow,FSR[3],underflow,FSR[5],inexact}) + 7'b1xxxxxx : tt = 3'b101; // Invalid operation + 7'b001xxxx : tt = 3'b010; // Overflow + 7'b00011xx : tt = 3'b001; // Underflow + 7'b0000011 : tt = 3'b110; // Inexact Result + default : tt = 3'b000; // no error + endcase + + assign TT_SP = {(inexact & ~op_cmp),(underflow & ~op_cmp),tt}; + assign SP_CMP[2] = nan; + + // Underflow Special case and force ZERO + assign FP_OUT = (underflow | fpout[36]) ? 32'd0 : {fpout[35],rund[32:2]}; + +endmodule diff --git a/src/m32632/STEUERUNG.v b/src/m32632/STEUERUNG.v new file mode 100644 index 0000000..8b9a4e5 --- /dev/null +++ b/src/m32632/STEUERUNG.v @@ -0,0 +1,220 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: STEUERUNG.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// STEUERUNG The control logic of M32632 +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module STEUERUNG( BCLK, BRESET, DC_ACC_DONE, ACB_ZERO, DONE, INT_N, NMI_N, DC_ABORT, IC_INIT, DC_INIT, SAVE_PC, CFG, + IACC_STAT, PROT_ERROR, IC_DIN, PC_NEW, PSR, STRING, TRAPS, IC_READ, DATA_HOLD, LD_DIN, LD_IMME, + WREN, WR_REG, GENSTAT, ILO, COP_OP, IC_USER, ACC_FELD, DISP, IC_TEX, IMME_Q, INFO_AU, LD_OUT, + DETOIP, MMU_UPDATE, OPER, PC_ARCHI, PC_ICACHE, RDAA, RDAB, START, WMASKE, WRADR, RWVAL, Y_INIT, + ENA_HK, STOP_CINV ); + +input BCLK; +input BRESET; +input DC_ACC_DONE; +input ACB_ZERO; +input DONE; +input INT_N; +input NMI_N; +input DC_ABORT; +input IC_INIT; +input DC_INIT; +input SAVE_PC; +input Y_INIT; +input [8:0] CFG; +input [3:0] IACC_STAT; +input PROT_ERROR; +input [31:0] IC_DIN; +input [31:0] PC_NEW; +input [11:0] PSR; +input [4:0] STRING; +input [5:0] TRAPS; +input STOP_CINV; + +output IC_READ; +output DATA_HOLD; +output LD_DIN; +output LD_IMME; +output WREN; +output WR_REG; +output [2:0] GENSTAT; +output IC_USER; +output [14:0] ACC_FELD; +output [31:0] DISP; +output [2:0] IC_TEX; +output [31:0] IMME_Q; +output [6:0] INFO_AU; +output [1:0] LD_OUT; +output [12:0] DETOIP; +output [1:0] MMU_UPDATE; +output [10:0] OPER; +output [31:0] PC_ARCHI; +output [31:0] PC_ICACHE; +output [7:0] RDAA; +output [7:0] RDAB; +output [1:0] START; +output [1:0] WMASKE; +output [5:0] WRADR; +output [2:0] RWVAL; +output ENA_HK; +output ILO; +output [23:0] COP_OP; + +wire [55:0] OPREG; +wire IC_ABORT; +wire INIT_DONE; +wire UNDEF; +wire ILLEGAL; +wire [2:0] ANZ_VAL; +wire [31:0] PC_SAVE; +wire NEW; +wire RESTART; +wire STOP_IC; +wire [1:0] ALSB; +wire [2:0] USED; +wire NEXT_ADR; +wire NEW_PC; +wire NEXT_PCA; +wire LOAD_PC; +wire [31:0] DISP_BR; + +DECODER BEFEHLS_DEC( + .BCLK(BCLK), + .BRESET(BRESET), + .ACC_DONE(DC_ACC_DONE), + .ACB_ZERO(ACB_ZERO), + .DONE(DONE), + .NMI_N(NMI_N), + .INT_N(INT_N), + .DC_ABORT(DC_ABORT), + .IC_ABORT(IC_ABORT), + .INIT_DONE(INIT_DONE), + .UNDEF(UNDEF), + .ILL(ILLEGAL), + .IC_READ(IC_READ), + .ANZ_VAL(ANZ_VAL), + .CFG(CFG), + .OPREG(OPREG), + .PC_SAVE(PC_SAVE), + .PSR(PSR), + .STRING(STRING), + .TRAPS(TRAPS), + .NEW(NEW), + .WREN(WREN), + .LD_DIN(LD_DIN), + .LD_IMME(LD_IMME), + .NEXT_PCA(NEXT_PCA), + .WR_REG(WR_REG), + .LOAD_PC(LOAD_PC), + .GENSTAT(GENSTAT), + .RESTART(RESTART), + .STOP_IC(STOP_IC), + .ACC_FELD(ACC_FELD), + .DISP(DISP), + .DISP_BR(DISP_BR), + .IMME_Q(IMME_Q), + .INFO_AU(INFO_AU), + .LD_OUT(LD_OUT), + .DETOIP(DETOIP), + .MMU_UPDATE(MMU_UPDATE), + .OPER(OPER), + .RDAA(RDAA), + .RDAB(RDAB), + .START(START), + .USED(USED), + .WMASKE(WMASKE), + .WRADR(WRADR), + .RWVAL(RWVAL), + .ENA_HK(ENA_HK), + .ILO(ILO), + .COP_OP(COP_OP), + .STOP_CINV(STOP_CINV) ); + +ILL_UNDEF CHECKER( + .USER(PSR[8]), + .ANZ_VAL(ANZ_VAL), + .CFG(CFG[3:1]), + .OPREG(OPREG[23:0]), + .ILL(ILLEGAL), + .UNDEF(UNDEF)); + +OPDEC_REG OPC_REG( + .BCLK(BCLK), + .BRESET(BRESET), + .NEW(NEW), + .DC_INIT(DC_INIT), + .IC_INIT(IC_INIT), + .Y_INIT(Y_INIT), + .RESTART(RESTART), + .STOP_IC(STOP_IC), + .ACC_STAT(IACC_STAT), + .PROT_ERROR(PROT_ERROR), + .ALSB(ALSB), + .IC_DIN(IC_DIN), + .USED(USED), + .IC_READ(IC_READ), + .NEXT_ADR(NEXT_ADR), + .DATA_HOLD(DATA_HOLD), + .NEW_PC(NEW_PC), + .ABORT(IC_ABORT), + .INIT_DONE(INIT_DONE), + .ANZ_VAL(ANZ_VAL), + .IC_TEX(IC_TEX), + .OPREG(OPREG)); + +PROG_COUNTER PCS( + .BCLK(BCLK), + .BRESET(BRESET), + .NEXT_ADR(NEXT_ADR), + .NEW_PC(NEW_PC), + .NEXT_PCA(NEXT_PCA), + .NEW(NEW), + .LOAD_PC(LOAD_PC), + .USER(PSR[8]), + .SAVE_PC(SAVE_PC), + .FPU_TRAP(TRAPS[0]), + .ADIVAR(INFO_AU[3]), + .DISP(DISP_BR), + .PC_NEW(PC_NEW), + .USED(USED), + .IC_USER(IC_USER), + .ALSB(ALSB), + .PC_ARCHI(PC_ARCHI), + .PC_ICACHE(PC_ICACHE), + .PC_SAVE(PC_SAVE)); + +endmodule diff --git a/src/m32632/STEUER_MISC.v b/src/m32632/STEUER_MISC.v new file mode 100644 index 0000000..8c9f5d2 --- /dev/null +++ b/src/m32632/STEUER_MISC.v @@ -0,0 +1,962 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: STEUER_MISC.v +// Version: 1.1 bug fix +// History: 1.0 first release of 30 Mai 2015 +// Date: 21 January 2016 +// +// Copyright (C) 2016 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. OPDEC_REG Central Instruction Register +// 2. PROG_COUNTER Program Counters +// 3. REG_LIST Register List Evaluation +// 4. ILL_UNDEF Illegal and Undefined Opcodes Detection +// 5. GRUPPE_2 Decoder and State Machine for GRUPPE_2 Opcodes +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. OPDEC_REG Central Instruction Register +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module OPDEC_REG ( BCLK, BRESET, NEW, ACC_STAT, PROT_ERROR, ALSB, USED, IC_DIN, IC_INIT, DC_INIT, Y_INIT, RESTART, STOP_IC, + OPREG, ANZ_VAL, IC_READ, NEW_PC, NEXT_ADR, DATA_HOLD, ABORT, IC_TEX, INIT_DONE); + + input BCLK,BRESET; + input NEW; // a program jump took place + input [3:0] ACC_STAT; // ICACHE signals data is available or Abort + input PROT_ERROR; // comes direct from ICACHE + input [1:0] ALSB; // lower addressbits of access address to ICACHE + input [2:0] USED; // Message from DECODER how many bytes were used + input [31:0] IC_DIN; // ICACHE Data + input IC_INIT,DC_INIT,Y_INIT; // Initialising or new setting is running + input RESTART; // "Break" of Instruction Pipeline - set up new i.e. after load of PSR + input STOP_IC; // For LMR and CINV + + output [55:0] OPREG; // this is the Central Opcode Decode Register, length = 7 bytes + output [2:0] ANZ_VAL; + output IC_READ; + output NEW_PC; + output NEXT_ADR; + output DATA_HOLD; + output ABORT; + output [2:0] IC_TEX; + output INIT_DONE; + + reg [55:0] OPREG; + reg [2:0] ANZ_VAL; + reg IC_READ; + reg ABORT; + reg abort_flag; + reg [2:0] IC_TEX; + reg [55:0] data_to_ri; + reg old_init; + reg pre_new; + reg new_reg; + reg nseq_flag; + reg stop_init; + + wire [2:0] new_anz; + wire new_restart; + wire acc_err,acc_ok,acc_ende; + + // ++++++++++++++++++++ Evaluation of ACC_STAT from Instructioncache ++++++++++++++++++++++++++++ + + // ACC_STAT[3:0] : PROT_ERROR , ABO_LEVEL1 , ABORT , ACC_OK + + assign acc_err = ACC_STAT[3] | ACC_STAT[1] | PROT_ERROR; + assign acc_ok = ACC_STAT[0]; + + always @(posedge BCLK or negedge BRESET) // is kept until DECODER really needs the data ! + if (!BRESET) ABORT <= 1'b0; + else ABORT <= (acc_err & ~(new_restart | pre_new)) | (ABORT & ~NEW_PC); + + always @(posedge BCLK) if (acc_err) IC_TEX <= (ACC_STAT[3] | PROT_ERROR) ? {nseq_flag,2'b11} : {nseq_flag,~ACC_STAT[2],ACC_STAT[2]}; + + always @(posedge BCLK) nseq_flag <= NEW_PC | (nseq_flag & ~acc_ok); // for MMU Status Register + + always @(posedge BCLK) abort_flag <= acc_err; + assign acc_ende = ~IC_READ | acc_ok | abort_flag; // abort_flag one cycle later is ok ! If no ICache access always end + + assign new_restart = NEW | RESTART; // They are pulses + + // Branch work out : NEW/RESTART notice if access still not ended + always @(posedge BCLK) pre_new <= (new_restart & ~acc_ende) | (pre_new & ~acc_ende & BRESET); + + assign NEW_PC = (new_restart | pre_new) & acc_ende; // At the end of access geenerate new address ! + + // There are 2 "NEW/RESTART" : "new_restart" combinatorical out of DECODER, "pre_new" out of Register + always @(posedge BCLK) new_reg <= new_restart | pre_new | (new_reg & ~acc_ende & BRESET); + + always @(USED or OPREG) // Data first shift to the right + case (USED) + 3'b000 : data_to_ri = OPREG; + 3'b001 : data_to_ri = { 8'hxx, OPREG[55:8]}; + 3'b010 : data_to_ri = {16'hxxxx,OPREG[55:16]}; + 3'b011 : data_to_ri = {24'hxx_xxxx,OPREG[55:24]}; + 3'b100 : data_to_ri = {32'hxxxx_xxxx,OPREG[55:32]}; + 3'b101 : data_to_ri = {40'hxx_xxxx_xxxx,OPREG[55:40]}; + 3'b110 : data_to_ri = {48'hxxxx_xxxx_xxxx,OPREG[55:48]}; + 3'b111 : data_to_ri = 56'hxx_xxxx_xxxx_xxxx; + endcase + + assign new_anz = ANZ_VAL - USED; + + always @(posedge BCLK) + casex ({new_reg,acc_ok,ALSB,new_anz}) + 7'b1_100_xxx : OPREG <= {24'hxx_xxxx,IC_DIN}; + 7'b1_101_xxx : OPREG <= {32'hxxxx_xxxx,IC_DIN[31:8]}; + 7'b1_110_xxx : OPREG <= {40'hxx_xxxx_xxxx,IC_DIN[31:16]}; + 7'b1_111_xxx : OPREG <= {48'hxxxx_xxxx_xxxx,IC_DIN[31:24]}; + 7'b0_0xx_xxx : OPREG <= data_to_ri; + 7'b0_1xx_000 : OPREG <= {24'hxx_xxxx,IC_DIN}; + 7'b0_1xx_001 : OPREG <= { 16'hxxxx,IC_DIN, data_to_ri[7:0]}; + 7'b0_1xx_010 : OPREG <= { 8'hxx,IC_DIN,data_to_ri[15:0]}; + 7'b0_1xx_011 : OPREG <= { IC_DIN,data_to_ri[23:0]}; + 7'b0_1xx_1xx : OPREG <= data_to_ri; + endcase + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) ANZ_VAL <= 3'b000; + else + casex ({new_restart,new_reg,acc_ok,new_anz[2]}) + 4'b1x_x_x : ANZ_VAL <= 3'b000; // hard setting to 0 + 4'b01_0_x : ANZ_VAL <= 3'b000; + 4'b01_1_x : ANZ_VAL <= pre_new ? 3'b000 : 3'b100 - {1'b0,ALSB}; + 4'b00_0_x : ANZ_VAL <= new_anz; + 4'b00_1_0 : ANZ_VAL <= new_anz + 3'b100; + 4'b00_1_1 : ANZ_VAL <= new_anz; + endcase + + assign NEXT_ADR = new_reg ? (acc_ok & ~pre_new) : (acc_ok & ~new_anz[2]); // switches MUX at PC resp. ICACHE + + // Instruction CACHE Control : READ is coming after all INITs are done + + always @(posedge BCLK) old_init <= IC_INIT | DC_INIT | Y_INIT; + + assign INIT_DONE = old_init & ~IC_INIT & ~DC_INIT; + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) stop_init <= 1'b0; + else stop_init <= stop_init | IC_READ; + + // The INIT_DONE should come after Reset. But it comes too at LMR PTB therefore extra enable after Reset ! + always @(posedge BCLK or negedge BRESET) + if (!BRESET) IC_READ <= 1'b0; + else IC_READ <= (IC_READ & ~acc_err & ~(STOP_IC & acc_ok)) | NEW_PC | (INIT_DONE & ~stop_init); + + // The Opcode-Register can not store the data : keep them in ICACHE at IO-access + assign DATA_HOLD = ~new_restart & ~new_reg & acc_ok & new_anz[2]; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. PROG_COUNTER Program Counters +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module PROG_COUNTER ( BCLK, BRESET, NEW, LOAD_PC, NEW_PC, NEXT_ADR, NEXT_PCA, DISP, PC_NEW, USED, USER, SAVE_PC, FPU_TRAP, + ADIVAR, PC_ARCHI, PC_ICACHE, PC_SAVE, ALSB, IC_USER); + + input BCLK,BRESET; + input NEW; + input LOAD_PC; + input NEW_PC; + input NEXT_ADR; + input NEXT_PCA; + input [31:0] DISP; + input [31:0] PC_NEW; + input [2:0] USED; + input USER; + input SAVE_PC; + input FPU_TRAP; + input ADIVAR; + + output [31:0] PC_ARCHI; // goes to Datapath + output [31:0] PC_ICACHE; + output [31:0] PC_SAVE; // is the return address + output [1:0] ALSB; + output IC_USER; + + reg [31:0] PC_ARCHI; + reg [31:0] pc_adduse; + reg [31:0] pc_ic_reg; + reg [31:0] fpu_trap_pc; + reg IC_USER; + + wire [31:0] branch,pc_jump,next_pc,pc_icache_i; + + assign PC_SAVE = pc_adduse + {29'h0,USED}; + assign branch = PC_ARCHI + DISP; + + assign pc_jump = LOAD_PC ? PC_NEW : branch; + + assign next_pc = NEW ? pc_jump : PC_SAVE; // Only at NEW is the DISP correct ! + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) pc_adduse <= 32'h0; + else + pc_adduse <= next_pc; + + // The Architectur - PC : Address mode "Programm Memory"-relativ + // no BRESET because NEXT_PCA is immediately valid + always @(posedge BCLK) + if (FPU_TRAP) PC_ARCHI <= fpu_trap_pc; // go back ! + else + if (NEXT_PCA) PC_ARCHI <= pc_adduse; + + always @(posedge BCLK) if (SAVE_PC) fpu_trap_pc <= PC_ARCHI; // Special storage for PC for FPU Trap + + always @(posedge BCLK or negedge BRESET) + if (!BRESET) pc_ic_reg <= 32'h0; + else + pc_ic_reg <= pc_icache_i; + + // NEW is only one cycle long - but in pc_adduse is the PC stored when ACC_OK is not there and therefore NEW_PC + // is used to initiate a new access in ICACHE + assign pc_icache_i = NEW_PC ? (NEW ? pc_jump : pc_adduse) : (NEXT_ADR ? ({pc_ic_reg[31:2],2'b00} + 32'h0000_0004) : pc_ic_reg); + + // This MUX is extra for LMR IVAR,... and CINV build in + assign PC_ICACHE = {(ADIVAR ? PC_NEW[31:4] : pc_icache_i[31:4]),pc_icache_i[3:0]}; + + assign ALSB = pc_ic_reg[1:0]; // for OPDEC_REG + + // The IC_USER flag is allowed to switch synchronously with one cycle delay to PC_ICACHE + always @(posedge BCLK or negedge BRESET) + if (!BRESET) IC_USER <= 1'b0; + else + if (NEW_PC) IC_USER <= USER; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. REG_LIST Register List Evaluation +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module REG_LIST ( DIN, IPOS, INIT, OPOS, VALID); + + // Detects set bits in register list for SAVE/RESTORE & ENTER/EXIT + + input [7:0] DIN; + input [2:0] IPOS; + input INIT; + output [2:0] OPOS; + output VALID; + + reg [7:1] filter; + wire [7:0] mdat_0; + wire [3:0] mdat_1; + wire [1:0] mdat_2; + + always @(IPOS or DIN) + case (IPOS) + 3'd0 : filter = DIN[7:1]; + 3'd1 : filter = {DIN[7:2],1'b0}; + 3'd2 : filter = {DIN[7:3],2'b0}; + 3'd3 : filter = {DIN[7:4],3'b0}; + 3'd4 : filter = {DIN[7:5],4'b0}; + 3'd5 : filter = {DIN[7:6],5'b0}; + 3'd6 : filter = {DIN[7] ,6'b0}; + 3'd7 : filter = 7'b0; + endcase + + assign mdat_0 = INIT ? DIN : {filter,1'b0}; + assign OPOS[2] = (mdat_0[3:0] == 4'h0); + assign mdat_1 = OPOS[2] ? mdat_0[7:4] : mdat_0[3:0]; + assign OPOS[1] = (mdat_1[1:0] == 2'b00); + assign mdat_2 = OPOS[1] ? mdat_1[3:2] : mdat_1[1:0]; + assign OPOS[0] = ~mdat_2[0]; + assign VALID = (mdat_2 != 2'b00); + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. ILL_UNDEF Illegal and Undefined Opcodes Detection +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ILL_UNDEF (OPREG, ANZ_VAL, USER, CFG, ILL, UNDEF ); + + input [23:0] OPREG; + input [2:0] ANZ_VAL; + input [3:1] CFG; // 3=CUSTOM,2=MMU,1=FPU + input USER; + + output reg ILL; + output UNDEF; + + reg undef_opc; + reg undef_am; + reg undef_im; + + wire [2:0] valid; + wire gen12,gen22,gen13,gen23; + wire igen12,igen22,igen13,igen23; + wire lsbes; + + parameter udef_amode = 5'b10011; // Undefined Addressing Mode + parameter imode = 5'b10100; // Immediate Addressing Mode + + // [2]= minimum 3, [1]= minimum 2, [0]=minimum 1 + assign valid = {(ANZ_VAL[2] | (ANZ_VAL[1:0] == 2'b11)),(ANZ_VAL[2:1] != 2'b00),(ANZ_VAL != 3'b000)}; + assign lsbes = (OPREG[1:0] == 2'b10); // Tag of all 3 Byte opcodes + + // +++++++++++++++++++++++++ Detect illegale opcodes +++++++++++++++++++ + + always @(OPREG or lsbes or valid or USER) + casex ({valid[2:1],OPREG[13:2],lsbes}) + 15'bx1_xx_x000_1x10_11_0 : ILL = USER; // SPRi/LPRi DCR + 15'bx1_xx_x001_xx10_11_0 : ILL = USER; // SPRi/LPRi BPC/DSR + 15'bx1_xx_xx10_xx10_11_0 : ILL = USER; // SPRi/LPRi CAR/CFG/PSR + 15'bx1_xx_x101_1x10_11_0 : ILL = USER; // SPRi/LPRi USP + 15'bx1_xx_x111_0x10_11_0 : ILL = USER; // SPRi/LPRi INTBASE + 15'bx1_xx_x0x1_0111_11_x : ILL = USER & OPREG[0]; // BICPSRW,BISPSRW + 15'bx1_00_10xx_0000_11_1 : ILL = USER; // SETCFG - Achtung : is coded as 2 Byte Opcode + 15'b1x_00_xxxx_0001_11_1 : ILL = USER; // LMR/SMR/RDVAL/WRVAL + 15'b1x_10_01xx_0001_11_1 : ILL = USER; // CINV + default : ILL = 1'b0; + endcase + + // ++++++++++++++++++++++++ Detect Undefined opcodes +++++++++++++++ + + always @(OPREG or lsbes or valid or CFG) + casex ({valid,OPREG[13:2],lsbes}) + 16'bx1x_xx_xxxx_1111_110 : undef_opc = 1'b1; // Format 3 : xxx1 + 16'bx1x_xx_x100_0111_110 : undef_opc = 1'b1; // Format 3 : 1000 + 16'b1xx_1x_xxxx_0000_111 : undef_opc = 1'b1; // Format 5 : 1xxx + 16'b1xx_01_xxxx_0000_111 : undef_opc = 1'b1; // Format 5 : 01xx + 16'b1xx_01_00xx_0100_111 : undef_opc = 1'b1; // Format 6 : 0100 + 16'b1xx_10_10xx_x100_111 : undef_opc = 1'b1; // Format 6/7 : 1010 + 16'b1xx_xx_xxxx_x011_111 : undef_opc = ~CFG[1]; // Format 9/11 : FPU Befehle wie MOVif etc. und ADDf etc. + 16'b1xx_xx_xxxx_1111_111 : undef_opc = ~CFG[1]; // Format 12 : FPU Befehle wie POLYf etc. + 16'b1xx_x1_xxxx_0001_111 : undef_opc = 1'b1; // Format 14 : x1xx + 16'b1xx_10_00xx_0001_111 : undef_opc = 1'b1; // Format 14 : 1000 + 16'b1xx_10_1xxx_0001_111 : undef_opc = 1'b1; // Format 14 : 101x + 16'b1xx_00_1xxx_0001_111 : undef_opc = ~CFG[2] | ~OPREG[18]; // Format 14 : LMR/SMR + 16'b1xx_xx_xxxx_x011_011 : undef_opc = ~CFG[3]; // Format 15.1/15.5 : CUSTOM CCV0, CCAL0 etc. + 16'b1xx_xx_xxxx_0001_011 : undef_opc = 1'b1; // Format 15.0 - not yet in, requires HW change + 16'b1xx_xx_xxxx_x1x1_011 : undef_opc = 1'b1; // Format 15 : rest + 16'b1xx_xx_xxxx_1001_011 : undef_opc = 1'b1; // Format 15.4 + // completely undefined : + 16'bxx1_xx_xxxx_0111_111 : undef_opc = 1'b1; // Format 10 + 16'bxx1_xx_xxxx_100x_111 : undef_opc = 1'b1; // Format 13/18 + 16'bxx1_xx_xxxx_x101_111 : undef_opc = 1'b1; // Format 16/17 + 16'bxx1_xx_xxxx_xxx0_011 : undef_opc = 1'b1; // Format 19 + default : undef_opc = 1'b0; + endcase + + // 2. Undefined Addressing mode 5'b10011 + + assign gen12 = (OPREG[15:11] == udef_amode); + assign gen22 = (OPREG[10:6] == udef_amode); + assign gen13 = (OPREG[23:19] == udef_amode); + assign gen23 = (OPREG[18:14] == udef_amode); + + always @(OPREG or valid or gen12 or gen22 or gen13 or gen23) + if (valid[2] && (OPREG[7:5] != 3'b000) && (OPREG[3:0] == 4'b1110)) undef_am = gen13 | gen23; // nearly all 3 Byte opcodes + else + undef_am = valid[1] & gen12 & (OPREG[1:0] != 2'b10) & ((OPREG[3:2] != 2'b11) & gen22); // all 2 Byte opcodes + + // 3. When is Immediate not allowed ? + + assign igen12 = (OPREG[15:11] == imode); + assign igen22 = (OPREG[10:6] == imode); + assign igen13 = (OPREG[23:19] == imode); + assign igen23 = (OPREG[18:14] == imode); + + always @(*) + casex ({valid[2:1],OPREG[13:2],lsbes}) + 15'bx1_xxxxxx_x0xx11_0 : undef_im = igen12 & (OPREG[5:4] != 2'b01); // Format 2 : ADDQD,SPR,Scond + 15'bx1_xxxxxx_x10111_0 : undef_im = igen12; // Format 2 : ACB,MOVQ + 15'bx1_xxxxx0_011111_0 : undef_im = igen12; // Format 3 : CXPD,JUMP,JSR + 15'bx1_xxxxxx_xxxxx0_0 : undef_im = igen22; // Format 4 + 15'bx1_xxxxxx_xxxx01_0 : undef_im = (igen12 & (OPREG[5:4] == 2'b10)) // Format 4 : SRC1 - not ADDR + |(igen22 & (OPREG[5:4] != 2'b00)); // Format 4 : SRC2 - CMP + 15'b1x_xxxxxx_x10011_1 : undef_im = igen23; // Format 6+7 + 15'b1x_xxx0xx_0x1011_1 : undef_im = igen13 | igen23; // Format 8 EXT,CVTP + 15'b1x_xxx0xx_101011_1 : undef_im = igen23; // Format 8 : INS + 15'b1x_xxx0xx_111011_1 : undef_im = igen13; // Format 8 : CHECK + 15'b1x_xxx1xx_101011_1 : undef_im = igen13 | igen23; // Format 8 MOVUS,MOVSU + 15'b1x_xxx1xx_011011_1 : undef_im = igen23; // Format 8 : FFS + 15'b1x_xxxxxx_001111_1 : undef_im = igen23; // Format 9 + 15'b1x_xxxxxx_101111_1 : undef_im = igen23 & (OPREG[13:10] != 4'h2); // Format 10 without CMPf + 15'b1x_010xxx_111111_1 : undef_im = igen23; // Format 12 SCALB+LOGB + 15'b1x_000xxx_000111_1 : undef_im = igen13; // Format 14 RDVAL+WRVAL + 15'b1x_0011xx_000111_1 : undef_im = igen13; // Format 14 SMR + default : undef_im = 1'b0; + endcase + + // Final Message : + + assign UNDEF = undef_opc | undef_am | undef_im; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 5. GRUPPE_2 Decoder and State Machine for GRUPPE_2 Opcodes +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module GRUPPE_2 ( BCLK, PHASE_0, OPREG, PHASE, SRC_1, SRC_2, REGA1, REGA2, IRRW1, IRRW2, ADRD1, ADRD2, EXR12, EXR22, + PHRD1, PHRD2, NXRD1, NXRW2, ACCA, OPERA, + STATE_0, STATE_GROUP_50, STATE_GROUP_60 ); + + + input BCLK,PHASE_0; + input [18:0] OPREG; + input [3:0] PHASE; // nur die 4 LSBs + // Source 1 & 2 Inputs + input [6:0] SRC_1,SRC_2,REGA1,REGA2,IRRW1,IRRW2; + input [18:0] ADRD1,ADRD2,EXR12,EXR22; + input [3:0] PHRD1,PHRD2; + input [3:0] NXRD1,NXRW2; + input [3:0] ACCA; // ACCA = Access type : 0x Register + // [3:2] or [1:0] 10 Memory + // 11 Memory + Index + input [10:0] OPERA; + + output [66:0] STATE_0; + output [66:0] STATE_GROUP_50,STATE_GROUP_60; + + reg [66:0] STATE_GROUP_50,STATE_GROUP_60; + reg [66:0] STATE_0,state_50,state_53,state_54,state_55,state_58,state_59,state_5A; + reg [4:0] op_code,op_reg_reg; + reg [7:0] phsrc1,phsrc2; + reg [5:0] chkreg; + reg [1:0] bwdreg; + reg tbit_flag,size_dw; + reg inss_flag; + reg ext_tos; + + wire [18:0] exoffset,re_wr,rexwr; + wire [10:0] op_kust,op_bwd; + wire [7:0] phchk; + wire [4:0] op_reg; + wire [6:0] src_1l,src_2l; + wire [5:0] dest_2; + wire [3:0] get8b_s,get8b_d; + wire [6:0] rd_reg; + wire [10:0] op_zext; + wire [3:0] imdi; + + parameter dont_care = 67'hx_xxxx_xxxx_xxxx_xxxx; + // Address-Field : Size:2 RD WR LDEA FULLACC INDEX:4 SPUPD disp_val:4 POST CLRMSW SRC2SEL:2 + parameter addr_nop = 19'h0; // alle Parameter auf 0 + parameter disp2ea = 19'bxx_0010_0000_0_0000_0010; // pass DISP + parameter case_op = 19'bxx_0010_1000_0_0000_0001; // SRC1 add to PC_ARCHI + parameter read_byb = 19'b00_1011_11xx_0_0000_0011; // read of SRC2 for Bit opcodes + parameter exr11 = {2'b10 ,4'b1011,4'h0 ,9'h080}; // 2. access External with Mem.-Pointer + 4* Disp + parameter adrcvtp = 19'bxx_0010_0111_0_0000_0000; // for CVTP + parameter addone = 19'bxx_0010_0100_0_0000_0000; // for INDEX : SRC1 + SRC2 , simple Add without Flags + parameter addind = 19'bxx_0010_0100_0_0000_0011; // for INDEX : SRC1 + EA + parameter src_x = 7'hxx; + parameter dest_x = 6'hxx; + parameter imme = {1'b1,6'hxx}; + parameter F0 = 7'h20; + parameter F0_h = 7'h21; + parameter w_F0 = 6'h20; + parameter w_F0_h = 6'h21; + parameter temp_l = 6'h3C; + parameter temp_h = 6'h3D; // Second last place for 8B TEMP Register + parameter temp_1 = 6'h3E; + parameter rtmpl = 7'h3C; + parameter rtmph = 7'h3D; + parameter rtmp1 = 7'h3E; + parameter op_mov = {3'bx1x,8'h45}; + parameter op_adr = {3'bx1x,8'h49}; + parameter op_addl = {3'b01x,8'hB0}; + parameter op_addf = {3'b11x,8'hB0}; + parameter op_mull = {3'b01x,8'hBC}; + parameter op_mulf = {3'b11x,8'hBC}; + parameter op_truf = {3'b101,8'h9A}; // TRUNCFW for SCALBF + parameter op_trul = {3'b001,8'h9A}; // TRUNCLW for SCALBL + parameter op_stpr = {3'b11x,8'h54}; // Special-Op for String opcodes + parameter op_lsh = {3'b011,8'h65}; // EXT : shift to right : DOUBLE ! + parameter op_msk = {3'b011,8'h80}; // reuse of EXT Opcode at INS ! + parameter op_mul = {3'b011,8'h78}; // INDEX + parameter op_rwv = {3'bx1x,8'hE0}; // RDVAL+WRVAL + + always @(OPREG) // whether the Opcode is valid is decided in DECODER ! + casex (OPREG[13:0]) +// 14'bxx_xxxx_1111_1110 : op_code = {2'b01,OPREG[11:10],OPREG[8]}; // DOT/POLY/SCALB + 14'b00_0xxx_0000_1110 : op_code = 5'b1_0000; // MOVS/CMPS + 14'b00_11xx_0000_1110 : op_code = 5'b1_0000; // SKPS + 14'b00_0xxx_1100_1110 : op_code = 5'b1_0001; // MOVM/CMPM + 14'bxx_xx10_0111_11xx : op_code = 5'b1_0010; // JUMP/JSR + 14'bxx_x111_0111_11xx : op_code = 5'b1_0011; // CASE + 14'bxx_xxxx_xx11_010x : op_code = 5'b1_0100; // TBIT + 14'bxx_xxxx_xx11_0111 : op_code = 5'b1_0100; // TBIT + 14'b0x_1xxx_0100_1110 : op_code = 5'b1_0100; // CBIT/SBIT + 14'b11_10xx_0100_1110 : op_code = 5'b1_0100; // IBIT + 14'b00_11xx_1100_1110 : op_code = 5'b1_0101; // EXTS + 14'b10_x1xx_1100_1110 : op_code = 5'b1_0111; // DEI/MEI + 14'bxx_x0xx_1110_1110 : op_code = 5'b1_1000; // CHECK + 14'bxx_x0xx_0010_1110 : op_code = 5'b1_1010; // EXT + 14'bxx_x0xx_1010_1110 : op_code = 5'b1_1011; // INS + 14'b00_10xx_1100_1110 : op_code = 5'b1_1011; // INSS, the same like INS ! + 14'bxx_x0xx_0110_1110 : op_code = 5'b1_1100; // CVTP + 14'bxx_x1xx_0010_1110 : op_code = 5'b1_1101; // INDEX + 14'bxx_x000_0111_11xx : op_code = 5'b1_1110; // CXPD + 14'b00_0xxx_0001_1110 : op_code = 5'b1_1111; // RDVAL+WRVAL + default : op_code = 5'b00_xxx; + endcase + + always @(posedge BCLK) if (PHASE_0) op_reg_reg <= op_code; + assign op_reg = PHASE_0 ? op_code : op_reg_reg; + + always @(PHRD1) // recode of States + casex (PHRD1) + 4'h5 : phsrc1 = 8'h51; + 4'h6 : phsrc1 = 8'h52; + 4'hB : phsrc1 = 8'h53; // ok, is in default ... + default : phsrc1 = 8'h53; + endcase + + assign get8b_s = (PHRD1 == 4'hB) ? 4'hC : 4'h0; // Special case 8B Immeadiate, is used in State 53 + + always @(PHRD2) // recode of States + casex (PHRD2) + 4'h5 : phsrc2 = 8'h56; + 4'h6 : phsrc2 = 8'h57; + 4'hB : phsrc2 = 8'h58; // ok, is in default ... + default : phsrc2 = 8'h58; + endcase + + assign get8b_d = (PHRD2 == 4'hB) ? 4'hC : 4'h0; // Special case 8B Immeadiate, is used in State 58 + + assign src_1l = {SRC_1[6:1],1'b0}; + assign src_2l = {SRC_2[6:1],~SRC_2[0]}; // needed only for DEI/MEI + assign dest_2 = SRC_2[5:0]; + + assign phchk = {7'b0101_010,size_dw}; // Phase 54 or 55 + + assign op_kust = {1'bx,OPERA[9:8],8'h7A}; // Special-Opcode for MOVM/CMPM + assign op_bwd = {1'bx,OPERA[9:8],8'h45}; // for CASE and Bit opcodes + + assign re_wr = {EXR22[18:17],4'b0101,4'h0, 9'h003}; // REUSE Address : Write of rmw , top 2 Bits contain size + + always @(posedge BCLK) if (PHASE_0) ext_tos <= (OPREG[18:14] == 5'h17); // if TOS + assign rexwr = {EXR22[18:17],4'b0101,4'h0, ext_tos, 8'h03}; // REUSE Addresse : Write von rmw , only for EXT and EXTS ! + + always @(posedge BCLK) tbit_flag <= ~OPERA[1]; // due to Timing ... + always @(posedge BCLK) size_dw <= OPERA[9]; + + always @(posedge BCLK) if (PHASE_0) chkreg <= {3'b000,OPREG[13:11]}; // for CHECK + assign rd_reg = (PHASE_0) ? {4'b0,OPREG[13:11]} : {1'b0,chkreg}; // for read operation at EXT/INS + + always @(posedge BCLK) if (PHASE_0) bwdreg <= OPREG[9:8]; // only for INS/INSS ! + assign op_zext = {1'bx,(PHASE_0 ? OPREG[9:8] : bwdreg),8'h76}; + + always @(posedge BCLK) if (PHASE_0) inss_flag <= OPREG[6]; // Difference INSS to INS + assign imdi = inss_flag ? 4'h8 : 4'hE; // read Immediate or Displacement + assign exoffset = inss_flag ? 19'b10_1011_0000_0_0000_0011 // Read of SRC2 at INSS + : 19'b10_1011_1100_0_0000_0011; // Read of SRC1+Offset at EXT, SRC2+Offset at INS + + always @(*) + casex (op_reg) + 5'b1_0000 : // MOVS Phase 0 : Entry 1. Pointer "in Page"-test prepare, 2. test for R0=0 , then jump to x'C0 + begin + STATE_0 = { addr_nop,8'h67, 7'h01, 7'h02, 1'b0,dest_x,op_stpr, 2'b00,2'b00,4'h0 }; // String-Pointer prepare + state_50 = dont_care; + state_53 = dont_care; + state_54 = dont_care; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + 5'b1_0001 : // MOVM Phase 0 : Entry with test for R0=0 , then jump to x'C0 + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b1,temp_h,op_adr, 2'b00,2'b00,NXRW2 }; + state_54 = dont_care; + state_55 = dont_care; + state_58 = { disp2ea, 8'h65, src_x, src_x, 1'b1,temp_1,op_adr, 2'b00,2'b00,4'b1110 }; // Read of DISP for count + state_59 = { addr_nop,8'h67, rtmph, rtmp1, 1'b0,dest_x,op_stpr, 2'b00,2'b00,4'h0 }; // String-Pointer prepare + state_5A = dont_care; + end + 5'b1_0010 : // JUMP/JSR + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { addr_nop,8'h66, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 }; + state_54 = dont_care; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + 5'b1_1110 : // CXPD + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { addr_nop,8'h6B, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_54 = dont_care; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + 5'b1_1111 : // RDVAL+WRVAL + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { addr_nop,8'h00, src_x, src_x, 1'b0,dest_x,op_rwv, 2'b00,2'b10,4'h0 }; // LD_OUT set because of "F" + state_54 = dont_care; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + 5'b1_0011 : // CASE + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { case_op, 8'h54, SRC_1, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h0 }; + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // only one operand in mem. + state_53 = { case_op, 8'h54, imme, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h0 }; + state_54 = { addr_nop,8'h66, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 }; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + 5'b1_0100 : // all Bit opcodes with Bit in memory. RMW Test in Phase x'59 = Special case, otherwise x'58 + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_54 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; // here SRC1 => TEMP_H + state_55 = dont_care; + state_58 = { read_byb,8'h59, rtmph, src_x, 1'b0,dest_x,op_bwd, 2'b00,2'b00,4'h1 }; // next read of Byte + state_59 = tbit_flag ? + { addr_nop,8'h00, src_x, imme, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 } // TBIT end + : { re_wr, 8'h27, src_x, imme, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 }; // CBIT/SBIT/IBIT end + state_5A = dont_care; + end + 5'b1_0101 : // EXTS : BASE Operand => TEMP, calculate address of Destination + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_54 = ACCA[1] ? + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here Adr(DEST) => EA + : { addr_nop,8'h59, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h8 }; // 1 Byte Immediate read + state_55 = dont_care; + state_58 = { addr_nop,8'h59, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h8 }; // 1 Byte Immediate read + state_59 = ACCA[1] ? // _..M. + { rexwr, 8'h27, imme, rtmph, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory + : { addr_nop,8'h00, imme, rtmph, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Register + state_5A = dont_care; + end + 5'b1_1010 : // EXT : BASE Operand => TEMP, calculate address of Destination + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h55, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Addr => EA Reg + state_54 = ACCA[1] ? + ( ACCA[3] ? + {addr_nop,8'h5A, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 } + :{ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } ) // here Adr(DEST) => EA + : { addr_nop,8'h59, rd_reg,(ACCA[3] ? imme : rtmph), + 1'b1,temp_h,op_lsh, 2'b00,2'b00,4'hE }; // Displacement read + state_55 = { exoffset,8'h54, rd_reg,src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h1 }; // Read Source, EA reuse + state_58 = { addr_nop,8'h59, rd_reg,rtmph, 1'b1,temp_h,op_lsh, 2'b00,2'b00,4'hE }; // Displacement read + state_59 = ACCA[1] ? // _..M. + { rexwr, 8'h27, src_x, rtmph, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory + : { addr_nop,8'h00, src_x, rtmph, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Register + state_5A = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; // special case Mem-Mem + end + 5'b1_1011 : // INS/INSS : BASE Operand => TEMP, SRC2 read as Double ! RMW not tested (Phase x'6A) but uncritical + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; // zext(SRC1) => TEMP + state_54 = ACCA[1] ? + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here Adr(DEST) => EA + : { addr_nop,8'h5A, SRC_2, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,imdi }; // Imme./Disp. read + state_55 = { exoffset,8'h6A, rd_reg,src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h1 }; // Read Source, EA reuse + state_58 = { addr_nop,8'h55, src_x, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // + state_59 = ACCA[1] ? // _..M. + { re_wr, 8'h27, rtmph, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h1 } // result in memory + : { addr_nop,8'h00, rtmph, rtmpl, 1'b1,dest_2,OPERA, 2'b00,2'b00,4'h0 }; // result in Register + state_5A = { addr_nop,8'h68, imme, src_x, 1'b1,temp_1,op_msk, 2'b00,2'b00,4'h0 }; // Mask generate + end + 5'b1_1101 : // INDEX : + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_zext, 2'b00,2'b00,4'h0 }; // zext(SRC1) => TEMP_H + state_54 = ACCA[1] ? + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // zext(SRC2) => TEMP_L + : { addr_nop,8'h55, SRC_2, src_x, 1'b1,temp_l,op_zext, 2'b00,2'b00,4'h0 }; + state_55 = { addr_nop,8'h5A, rd_reg,rtmph, 1'b1,temp_h,op_mul, 2'b00,2'b00,4'h0 }; // Multiplication + state_58 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_l,op_zext, 2'b00,2'b00,4'h0 }; // + state_59 = { addind, 8'h60, rtmpl, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Add of Index in EA + state_5A = { addone, 8'h59, rd_reg,rtmph, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // Add of EA (=+1) + end + 5'b1_0111 : // DEI + MEI , both read 8B from DEST ! RMW critical ! + begin + STATE_0 = ACCA[3] ? // _M... + { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_50 = ACCA[3] ? // _M... + { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } + : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; + state_54 = ACCA[1] ? + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } // here SRC1 => TEMP_H + : { addr_nop,8'h59, rtmph, SRC_2, 1'b0,dest_x,OPERA, 2'b01,2'b00,4'h0 }; // 1. part of Register + state_55 = dont_care; + state_58 = size_dw ? + { addr_nop,8'h59, rtmph, imme, 1'b0,dest_x,OPERA, 2'b01,2'b00,4'h0 } // D needs 2 accesses + : { addr_nop,8'h1F, rtmph, imme, 1'b0,dest_x,OPERA, 2'b11,2'b00,4'h0 }; // B+W start at once + state_59 = { addr_nop,8'h1F, src_x, (ACCA[1] ? imme : src_2l), // SRC2 = memory or Reg + ~ACCA[1],dest_2,OPERA, 2'b10,2'b00,4'h0 }; + state_5A = dont_care; + end + 5'b1_1000 : // CHECK + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // No Register ! + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { addr_nop,phchk, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 }; // No Immediate ! + state_54 = ACCA[1] ? + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } + : ( size_dw ? + {addr_nop,8'h5A, SRC_2, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 } // Upper Bound - pointer + : {addr_nop,8'h00, rtmph, SRC_2, 1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 } ); + state_55 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 }; + state_58 = size_dw ? + { addr_nop,8'h59, imme, src_x, 1'b1,temp_1,op_mov, 2'b00,2'b00,4'h0 } // here SRC2 => TEMP_1 + : { addr_nop,8'h00, rtmph, imme, 1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 }; + state_59 = { addr_nop,8'h5A, rtmp1, rtmpl, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 }; // Upper Bound - pointer + state_5A = { addr_nop,8'h00, rtmph, (ACCA[1] ? rtmp1 : SRC_2), + 1'b1,chkreg,OPERA, 2'b00,2'b10,4'h0 }; // pointer - Lower Bound + end + 5'b1_1100 : // CVTP + begin + STATE_0 = { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; // Address + state_50 = { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 }; + state_53 = { addr_nop,8'h54, src_x, src_x, 1'b1,temp_h,op_adr, 2'b00,2'b00,4'h0 }; + state_54 = { adrcvtp, 8'h73, rtmph, rd_reg,1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // 8*TEMP+Offset + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end +// 5'b01_000 : // SCALBL : RMW critical ! +// begin +// STATE_0 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, src_1l,1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 }; +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, src_1l,1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 }; +// state_53 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,get8b_s }; +// state_54 = ACCA[1] ? +// { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_trul, 2'b00,2'b00,NXRW2 } +// : { addr_nop,8'h5A, src_x, src_x, 1'b0,temp_h,op_trul, 2'b00,2'b00,4'h0 }; +// state_55 = { addr_nop,8'h54, rtmph, imme, 1'b1,temp_h,op_trul, 2'b11,2'b00,4'h0 }; // 2. half of external SRC1 +// state_58 = { addr_nop,8'h59, rtmph, imme, 1'b0,dest_2,OPERA, 2'b01,2'b00,4'h0 }; +// state_59 = { addr_nop,8'h1F, src_x, (ACCA[1] ? imme : src_2l), +// ~ACCA[1],dest_2,OPERA, 2'b10,2'b00,4'h0 }; +// state_5A = { addr_nop,8'h59, rtmph, SRC_2, 1'b0,dest_2,OPERA, 2'b01,2'b00,4'h0 }; // empty cycle for TRUNC => TEMP ! +// end +// 5'b01_001 : // SCALBF : RMW critical ! +// begin +// STATE_0 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 }; +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 }; +// state_53 = { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_truf, 2'b00,2'b00,4'h0 }; +// state_54 = ACCA[1] ? +// { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } +// : { addr_nop,8'h1F, rtmph, SRC_2, 1'b1,dest_2,OPERA, 2'b11,2'b00,4'h0 }; +// state_55 = dont_care; +// state_58 = { addr_nop,8'h1F, rtmph, imme, 1'b0,dest_x,OPERA, 2'b11,2'b00,4'h0 }; +// state_59 = dont_care; +// state_5A = dont_care; +// end +// 5'b01_100 : // POLYL +// begin +// STATE_0 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 }; +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 }; +// state_53 = { addr_nop,8'h54, imme, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,get8b_s }; +// state_54 = { addr_nop,8'h64, (ACCA[3] ? imme : src_1l), +// F0, 1'b1,temp_h,op_mull, 2'b10,2'b00,4'h0 }; +// state_55 = dont_care; +// state_58 = { addr_nop,8'h59, imme, rtmph, 1'b0,dest_x,op_addl, 2'b01,2'b00,get8b_d }; +// state_59 = { addr_nop,8'h62, (ACCA[1] ? imme : src_2l), +// rtmpl, 1'b1,w_F0_h,op_addl, 2'b10,2'b00,4'h0 }; +// state_5A = dont_care; +// end +// 5'b01_101 : // POLYF +// begin +// STATE_0 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { addr_nop,8'h54, SRC_1, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; +// state_53 = { addr_nop,8'h54, imme, F0, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; +// state_54 = ACCA[1] ? +// { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } +// : { addr_nop,8'h00, rtmph, SRC_2, 1'b1,w_F0 ,op_addf, 2'b00,2'b00,4'h0 }; +// state_55 = dont_care; +// state_58 = { addr_nop,8'h00, rtmph, imme, 1'b1,w_F0 ,op_addf, 2'b00,2'b00,4'h0 }; +// state_59 = dont_care; +// state_5A = dont_care; +// end +// 5'b01_110 : // DOTL +// begin +// STATE_0 = (~ACCA[3] & ~ACCA[1]) ? // _R.R. +// { addr_nop,8'h59, SRC_1, SRC_2, 1'b0,dest_x,op_mull, 2'b01,2'b00,4'h0 } +// : ( ACCA[3] ? // _M... +// {ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : {ADRD2, phsrc2,src_x, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } ); +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; +// state_53 = ACCA[1] ? // _..M. +// { addr_nop,8'h54, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,get8b_s } +// : { addr_nop,8'h59, imme, SRC_2, 1'b0,dest_x,op_mull, 2'b01,2'b00,get8b_s }; +// state_54 = { addr_nop,8'h55, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 }; +// state_55 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; +// state_58 = { addr_nop,8'h59, (ACCA[3] ? rtmph : SRC_1), //_M... +// imme, 1'b0,dest_x,op_mull, 2'b01,2'b00,get8b_d }; +// state_59 = { addr_nop,8'h5A, (ACCA[3] ? (ACCA[1] ? rtmpl : imme) : src_1l), (ACCA[1] ? imme : src_2l), +// 1'b1,temp_h,op_mull, 2'b10,2'b00,4'h0 }; +// state_5A = { addr_nop,8'h61, rtmph, F0_h, 1'b0,temp_h,op_mull, 2'b01,2'b00,4'h0 }; +// end +// 5'b01_111 : // DOTF +// begin +// STATE_0 = (~ACCA[3] & ~ACCA[1]) ? // _R.R. +// { addr_nop,8'h63, SRC_1 ,SRC_2 ,1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 } // opera = MULF +// : ( ACCA[3] ? // _M... +// {ADRD1, phsrc1,src_x, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : {ADRD2, phsrc2,src_x, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 } ); +// state_50 = ACCA[3] ? // _M... +// { ADRD1, phsrc1,IRRW1, REGA1, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRD1 } +// : { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; +// state_53 = ACCA[1] ? // _..M. +// { addr_nop,8'h55, imme, src_x, 1'b1,temp_h,op_mov, 2'b00,2'b00,4'h0 } +// : { addr_nop,8'h63, imme, SRC_2 ,1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; +// state_54 = dont_care; +// state_55 = { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,dest_x,op_mov, 2'b00,2'b00,NXRW2 }; +// state_58 = { addr_nop,8'h63, (ACCA[3] ? rtmph : SRC_1), //_M... +// imme, 1'b1,temp_h,op_mulf, 2'b00,2'b00,4'h0 }; +// state_59 = dont_care; +// state_5A = dont_care; +// end + default + begin + STATE_0 = dont_care; + state_50 = dont_care; + state_53 = dont_care; + state_54 = dont_care; + state_55 = dont_care; + state_58 = dont_care; + state_59 = dont_care; + state_5A = dont_care; + end + endcase + + always @(*) + casex (PHASE) + 4'h0 : STATE_GROUP_50 = state_50; + // Phase 51 : wait for data and Disp2 for External Address mode : part 2 EA = (MOD+4)+4*DISP1 + 4'h1 : STATE_GROUP_50 = {exr11, 8'h52, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}; + // Phase 52 : Memory-Pointer for Memory Relative and last access External + 4'h2 : STATE_GROUP_50 = {EXR12, 8'h53, IRRW1,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}; // atys[0] ! + 4'h3 : STATE_GROUP_50 = state_53; + 4'h4 : STATE_GROUP_50 = state_54; + 4'h5 : STATE_GROUP_50 = state_55; + // Phase 56 : wait for data and Disp2 for External Address mode : part 2 EA = (MOD+4)+4*DISP1 + 4'h6 : STATE_GROUP_50 = {exr11, 8'h57, src_x,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}; + // Phase 57 : Memory-Pointer for Memory Relative and last access External + 4'h7 : STATE_GROUP_50 = {EXR22, 8'h58, IRRW2,imme , 1'b0,dest_x, op_mov, 2'b00,2'b00, 4'b1111}; // atyd[0] ! + 4'h8 : STATE_GROUP_50 = state_58; + 4'h9 : STATE_GROUP_50 = state_59; + 4'hA : STATE_GROUP_50 = state_5A; + default : STATE_GROUP_50 = dont_care; + endcase + + always @(*) + casex (PHASE) + 4'h0 : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b1,chkreg,op_adr, 2'b00,2'b00,4'h0 }; // for INDEX + 4'h1 : STATE_GROUP_60 = { addr_nop,8'h62, rtmpl, F0, 1'b1,w_F0_h,op_addl, 2'b10,2'b00,4'h0 }; // for DOTL + 4'h2 : STATE_GROUP_60 = { addr_nop,8'h00, src_x, src_x, 1'b0,w_F0_h,op_addl, 2'b00,2'b00,4'h0 }; // for DOTL & POLYL ! + 4'h3 : STATE_GROUP_60 = { addr_nop,8'h00, rtmph, F0, 1'b1,w_F0, op_addf, 2'b00,2'b00,4'h0 }; // for DOTF + 4'h4 : STATE_GROUP_60 = ACCA[1] ? // ..M. + { ADRD2, phsrc2,IRRW2, REGA2, 1'b0,temp_h,op_mull, 2'b00,2'b00,NXRW2 } + : { addr_nop,8'h59, SRC_2, rtmph, 1'b0,temp_h,op_addl, 2'b01,2'b00,4'h0 }; // for POLYL + 4'h5 : STATE_GROUP_60 = { addr_nop,8'h59, src_x, src_x, 1'b1,temp_l,op_kust, 2'b00,2'b00,4'h0 }; // for MOVM/CMPM + 4'h6 : STATE_GROUP_60 = { addr_nop,8'h01, rtmph, src_x, 1'b0,dest_x,op_mov, 2'b00,2'b00,4'h0 }; // for JUMP/JSR/CASE + 4'h7 : STATE_GROUP_60 = { addr_nop,8'hC0, (op_reg_reg[0] ? rtmpl : 7'h00), // Jump to String execution + src_x, 1'b0,dest_x,OPERA, 2'b00,2'b10,4'h0 }; // LD_OUT set, CMPS F-Flag + // for INS + 4'h8 : STATE_GROUP_60 = { addr_nop,8'h69, rd_reg,rtmph, 1'b1,temp_h,op_lsh, 2'b00,2'b00,4'h0 }; // SRC1 shift + 4'h9 : STATE_GROUP_60 = { addr_nop,8'h59, rd_reg,rtmp1, 1'b0,dest_x,op_lsh, 2'b00,2'b00,4'h0 }; // Mask shift + 4'hA : STATE_GROUP_60 = { addr_nop,8'h5A, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,imdi }; // Imme./Disp. read + // for CXPD, this State is decoded explicitly in DECODER + 4'hB : STATE_GROUP_60 = { addr_nop,8'h39, imme, src_x, 1'b1,temp_l,op_mov, 2'b00,2'b00,4'h0 }; // pass PC + default : STATE_GROUP_60 = dont_care; + endcase + +endmodule diff --git a/src/m32632/TOP_MISC.v b/src/m32632/TOP_MISC.v new file mode 100644 index 0000000..7f1d3f3 --- /dev/null +++ b/src/m32632/TOP_MISC.v @@ -0,0 +1,164 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: TOP_MISC.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. IO_SWITCH Switch between ICACHE and DCACHE to IO Path +// 2. MAKE_STAT Generate Statistic Signals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. IO_SWITCH Switch between ICACHE and DCACHE to IO Path +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module IO_SWITCH ( BCLK, BRESET, I_IOA, D_IOA, I_IORD, D_IORD, D_IOWR, IO_READY, GENSTAT, D_IOBE, ILO_SIG, DCWACC, + IO_A, IO_RD, IO_WR, IO_BE, I_IORDY, D_IORDY, STATUS, ILO ); + + input BCLK,BRESET; + input [31:0] I_IOA,D_IOA; + input I_IORD; + input D_IORD,D_IOWR; + input [3:0] D_IOBE; + input IO_READY; + input [2:0] GENSTAT; + input ILO_SIG; + input [1:0] DCWACC; + + output [31:0] IO_A; + output IO_RD,IO_WR; + output [3:0] IO_BE; + output I_IORDY; + output D_IORDY; + output [3:0] STATUS; + output ILO; + + reg [3:0] STATUS; + reg [1:0] select; + reg ilo_flag; + + wire daten; + wire sel_dp; + wire interrupt; + wire ilo_keep; + + assign daten = D_IORD | D_IOWR; + + // DCACHE has priority. + always @(posedge BCLK or negedge BRESET) + if (!BRESET) select <= 2'b0; + else + casex ({I_IORD,D_IORD,D_IOWR,IO_READY,ilo_keep,select}) + 7'b000xx_00 : select <= 2'b00; + 7'b1000x_00 : select <= 2'b11; + 7'bx100x_00 : select <= 2'b10; + 7'bxx10x_00 : select <= 2'b10; + // the access has in the same cycle a READY ! + 7'b1001x_00 : select <= 2'b00; + 7'bx101x_00 : select <= 2'b00; + 7'bxx11x_00 : select <= 2'b00; + // Datea Access + 7'bxxx0x_10 : select <= 2'b10; + 7'bxxx11_10 : select <= 2'b10; // keep because of Interlocked + 7'bxxx10_10 : select <= 2'b00; + // Instruction Access + 7'bxxx0x_11 : select <= 2'b11; + 7'bxxx1x_11 : select <= 2'b00; + default : select <= 2'b00; + endcase + + assign sel_dp = (select == 2'b10) | ((select == 2'b00) & daten); + + assign IO_RD = sel_dp ? D_IORD : I_IORD; + assign IO_WR = sel_dp ? D_IOWR : 1'b0; + assign IO_A = sel_dp ? D_IOA : I_IOA; + assign IO_BE = sel_dp ? D_IOBE : 4'b1111; // Instruction read always 32 Bit + + assign D_IORDY = sel_dp & IO_READY; + assign I_IORDY = ~sel_dp & IO_READY; + + assign interrupt = GENSTAT[1] | GENSTAT[0]; + + always @(*) + casex ({sel_dp,daten,interrupt,I_IORD}) + 4'b110x : STATUS = 4'hA; // Daten + 4'b111x : STATUS = GENSTAT[1] ? 4'h4 : 4'h6; // Int Ack. : End of Int + 4'b0xx1 : STATUS = 4'h8; // Programm + default : STATUS = {3'd0,GENSTAT[2]}; // WAIT or Inactive + endcase + + // +++++++++++ ILO Control ++++++++++++++++++ + + always @(posedge BCLK) + if (!ILO_SIG) ilo_flag <= 1'b0; // Flag is set at read and cleared with write + else ilo_flag <= (D_IORD & sel_dp) | DCWACC[0] | ilo_keep; + + assign ilo_keep = ilo_flag & ~D_IOWR & ~DCWACC[1]; + + assign ILO = ILO_SIG & ((D_IORD & sel_dp) | DCWACC[0] | ilo_flag | D_IOWR | DCWACC[1]); + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. MAKE_STAT Generate Statistic Signals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module MAKE_STAT ( BCLK, READ, DACC_OK, DC_ACC, DPTE_ACC, DC_MDONE, DRAM_WR, IC_READ, IACC_OK, DATA_HOLD, + IC_ACC, IPTE_ACC, IC_MDONE, KOLLISION, STATSIGS ); + + input BCLK; + input READ,DACC_OK; + input DC_ACC,DPTE_ACC,DC_MDONE; + input DRAM_WR; + input IC_READ,IACC_OK,DATA_HOLD; + input IC_ACC,IPTE_ACC,IC_MDONE; + input KOLLISION; + + output reg [7:0] STATSIGS; + + always @(posedge BCLK) + begin + STATSIGS[7] <= KOLLISION; // 7 : from ICACHE : collisions + STATSIGS[6] <= IPTE_ACC; // 6 : Instruction PTE access + STATSIGS[5] <= IC_ACC & IC_MDONE; // 5 : Instruction Memory read + STATSIGS[4] <= IC_READ & IACC_OK & ~DATA_HOLD; // 4 : Instruction read , can be IO-Port too ! + STATSIGS[3] <= DRAM_WR; // 3 : Data write + STATSIGS[2] <= DPTE_ACC; // 2 : Data PTE access + STATSIGS[1] <= DC_ACC & DC_MDONE; // 1 : Data Memory read + STATSIGS[0] <= READ & DACC_OK; // 0 : Data read , can be IO-Port too ! + end + +endmodule + diff --git a/src/m32632/example.v b/src/m32632/example.v new file mode 100644 index 0000000..21e2801 --- /dev/null +++ b/src/m32632/example.v @@ -0,0 +1,209 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: example.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// example Your first system with the M32632 CPU +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +module example ( CLK, RESET_N, NMI_N, INT_N, IN_REG, OUT_REG); + +input CLK; +input RESET_N; +input NMI_N; +input INT_N; + +input [7:0] IN_REG; + +output [7:0] OUT_REG; + +reg nmi_reg,int_reg; + +wire IC_MDONE; +wire DC_MDONE; +wire ENWR; +wire WAMUX; +wire [11:2] WADDR; +wire [31:0] DRAM_Q; +wire [2:0] IWCTRL; +wire [2:0] DWCTRL; +wire IC_ACC; +wire [27:0] IDRAM_ADR; +wire DC_ACC; +wire DC_WR; +wire [27:0] DRAM_ADR; +wire [35:0] DRAM_DI; + +wire [31:0] IO_A; +wire [31:0] IO_DI; +wire [3:0] IO_BE; +wire IO_RD; +wire IO_WR; +wire IO_READY; +wire ENDRAM; +wire [31:0] IO_Q; +wire W_OUT_REG; +wire RST_N; + +wire [31:0] BOOT_DAT; +wire [31:0] STAT_DAT; +wire [7:0] IN_DAT; + +wire [7:0] STATSIGS; +wire COP_GO; +wire [23:0] COP_OP; +wire [127:0] COP_OUT; +wire COP_DONE; +wire [63:0] COP_IN; + +M32632 CPU( + // ++++++++++ Basic Signals + .BCLK(CLK), + .MCLK(~CLK), + .WRCFG(1'b1), + .BRESET(RST_N), + .NMI_N(nmi_reg), + .INT_N(int_reg), + .STATUS(), + .ILO(), + .STATSIGS(STATSIGS), + // +++++++++ General Purpose Interface + .IO_WR(IO_WR), + .IO_RD(IO_RD), + .IO_A(IO_A), + .IO_BE(IO_BE), + .IO_DI(IO_DI), + .IO_Q(IO_Q), + .IO_READY(IO_READY), + // +++++++++ DRAM Interface In + .ENDRAM(ENDRAM), + .IC_MDONE(IC_MDONE), + .DC_MDONE(DC_MDONE), + .ENWR(ENWR), + .WAMUX(WAMUX), + .WADDR(WADDR), + .DRAM_Q(DRAM_Q), + .DWCTRL(DWCTRL), + .IWCTRL(IWCTRL), + // +++++++++ DRAM Interface Out + .IC_ACC(IC_ACC), + .IDRAM_ADR(IDRAM_ADR), + .DC_ACC(DC_ACC), + .DC_WR(DC_WR), + .DRAM_ADR(DRAM_ADR), + .DRAM_DI(DRAM_DI), + // ++++++++++ DMA Interface + .HOLD(1'b1), + .HLDA(), + .FILLRAM(1'b0), + .DMA_AA(24'd0), + // ++++++++++ Coprocessor Interface + .COP_GO(COP_GO), + .COP_OP(COP_OP), + .COP_OUT(COP_OUT), + .COP_DONE(COP_DONE), + .COP_IN(COP_IN)); + +ex_io_bus_ctrl u_bus_ctrl( + .CLK(CLK), + .RESET_N(RESET_N), + .RST_N(RST_N), + .ENDRAM(ENDRAM), + .IO_WR(IO_WR), + .IO_RD(IO_RD), + .IO_A(IO_A[31:28]), + .IO_BE(IO_BE), + .IO_Q(IO_Q), + .IO_READY(IO_READY), + .W_OUT_REG(W_OUT_REG), + .IN_DAT(IN_DAT), + .BOOT_DAT(BOOT_DAT), + .STAT_DAT(STAT_DAT)); + +ex_in_reg u_in_reg( + .CLK(CLK), + .IN_REG(IN_REG), + .IN_DAT(IN_DAT)); + +ex_out_reg u_out_reg( + .CLK(CLK), + .OUT_REG(OUT_REG), + .W_OUT_REG(W_OUT_REG), + .DIN(IO_DI)); + +ex_boot_rom u_boot_rom( + .CLK(CLK), + .ADDR(IO_A[9:2]), + .DATA(BOOT_DAT)); + +ex_statcou u_statcou( + .CLK(CLK), + .RST_N(RST_N), + .STATSIGS(STATSIGS), + .ADDR(IO_A[4:2]), + .DATA(STAT_DAT)); + +ex_copro u_copro( + .CLK(CLK), + .COP_GO(COP_GO), + .COP_OP(COP_OP), + .COP_INP(COP_OUT), + .COP_DONE(COP_DONE), + .COP_OUTP(COP_IN)); + +ex_dram_emul u_dram_emul( + .MCLK(CLK), + .RST_N(RST_N), + .IC_ACC(IC_ACC), + .IDRAM_ADR(IDRAM_ADR), + .DC_ACC(DC_ACC), + .DC_WR(DC_WR), + .DRAM_ADR(DRAM_ADR), + .DRAM_DI(DRAM_DI), + .IC_MDONE(IC_MDONE), + .DC_MDONE(DC_MDONE), + .ENWR(ENWR), + .WAMUX(WAMUX), + .WADDR(WADDR), + .MEM_Q(DRAM_Q), + .DWCTRL(DWCTRL), + .IWCTRL(IWCTRL) ); + + always @(posedge CLK) // recommended to synchronize this signals + begin + nmi_reg <= NMI_N; + int_reg <= INT_N; + end + +endmodule diff --git a/src/m32632/example_mods.v b/src/m32632/example_mods.v new file mode 100644 index 0000000..b025c9b --- /dev/null +++ b/src/m32632/example_mods.v @@ -0,0 +1,356 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// This file is part of the M32632 project +// http://opencores.org/project,m32632 +// +// Filename: example_mods.v +// Version: 1.0 +// Date: 30 May 2015 +// +// Copyright (C) 2015 Udo Moeller +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, download it +// from http://www.opencores.org/lgpl.shtml +// +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Modules contained in this file: +// 1. ex_io_bus_ctrl Input/Output Bus controller +// 2. ex_in_reg Input Register +// 3. ex_out_reg Output Register +// 4. ex_boot_rom Boot ROM +// 5. ex_statcou Statistic Counters +// 6. ex_copro Coprocessor +// 7. ex_dram_emul DRAM Emulator +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 1. ex_io_bus_ctrl Input/Output Bus controller +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_io_bus_ctrl( CLK, RESET_N, RST_N, IO_WR, IO_RD, IO_A, IO_BE, IO_Q, IO_READY, + W_OUT_REG, IN_DAT, BOOT_DAT, STAT_DAT, ENDRAM ); + +input CLK; +input RESET_N; +input IO_WR,IO_RD; +input [31:28] IO_A; +input [3:0] IO_BE; + +input [31:0] BOOT_DAT; +input [7:0] IN_DAT; +input [31:0] STAT_DAT; + +output reg [31:0] IO_Q; +output reg RST_N; +output reg ENDRAM; +output IO_READY; +output W_OUT_REG; + +reg rd_rdy; +reg [3:0] init_cou; + + always @(posedge CLK) rd_rdy <= IO_RD & ~rd_rdy; + + assign IO_READY = IO_WR | rd_rdy; + + always @(IO_A or BOOT_DAT or IN_DAT or STAT_DAT) + casex({IO_A}) + 4'b000x : IO_Q = BOOT_DAT; // Boot-ROM + 4'b0010 : IO_Q = {24'd0,IN_DAT}; + 4'b0011 : IO_Q = STAT_DAT; + default : IO_Q = 32'hxxxxxxxx; + endcase + + assign W_OUT_REG = IO_WR & (IO_A == 4'h2) & IO_BE[0]; + + // ++++++++++++++++++++++++++ RESET Signal ++++++++++++++++++++++++++ + + always @(posedge CLK or negedge RESET_N) + if (!RESET_N) init_cou <= 4'h0; + else init_cou <= init_cou + 4'h1; + + always @(posedge CLK or negedge RESET_N) + if (!RESET_N) RST_N <= 1'b0; + else + if (init_cou == 4'hF) RST_N <= 1'b1; + + // Reading from Boot ROM switches DRAM on! You must read program code - not data. + always @(posedge CLK) ENDRAM <= (ENDRAM | (IO_RD & (IO_A == 4'h1))) & RST_N; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 2. ex_in_reg Input Register +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_in_reg( CLK, IN_REG, IN_DAT); + +parameter in_width = 7; + +input CLK; +input [in_width:0] IN_REG; + +output reg [in_width:0] IN_DAT; + +reg [in_width:0] meta_reg; + + always @(posedge CLK) + begin + meta_reg <= IN_REG; + IN_DAT <= meta_reg; + end + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 3. ex_out_reg Output Register +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_out_reg( CLK, W_OUT_REG, DIN, OUT_REG); + +parameter out_width = 7; + +input CLK; +input W_OUT_REG; +input [31:0] DIN; + +output reg [out_width:0] OUT_REG; + + always @(posedge CLK) if (W_OUT_REG) OUT_REG <= DIN[out_width:0]; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 4. ex_boot_rom Boot ROM +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_boot_rom( CLK, ADDR, DATA); + +input CLK; +input [9:2] ADDR; + +output reg [31:0] DATA; + +reg [31:0] BOOT_ROM [0:255]; // 1 kByte + +initial + begin + $readmemh("boot_rom.txt", BOOT_ROM); + end + + always @(posedge CLK) DATA <= BOOT_ROM[ADDR[9:2]]; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 5. ex_statcou Statistic Counters +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_statcou( CLK, RST_N, STATSIGS, ADDR, DATA); + +input CLK; +input RST_N; +input [7:0] STATSIGS; +input [2:0] ADDR; + +output [31:0] DATA; + +integer i; + +reg [31:0] counter [0:7]; + + always @(posedge CLK or negedge RST_N) + for (i=0; i<=7; i=i+1) + if (!RST_N) counter[i] <= 32'd0; + else counter[i] <= counter[i] + {31'd0,STATSIGS[i]}; + + assign DATA = counter[ADDR]; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 6. ex_copro Coprocessor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_copro( CLK, COP_GO, COP_OP, COP_INP, COP_DONE, COP_OUTP); + +input CLK; +input COP_GO; +input [23:0] COP_OP; +input [127:0] COP_INP; + +output reg COP_DONE; +output reg [63:0] COP_OUTP; + + always @(posedge CLK) + COP_OUTP <= COP_OP[8] ? {COP_INP[71:64],COP_INP[79:72],COP_INP[87:80],COP_INP[95:88],32'd0} + : {COP_INP[7:0],COP_INP[15:8],COP_INP[23:16],COP_INP[31:24],COP_INP[71:64],COP_INP[79:72],COP_INP[87:80],COP_INP[95:88]}; + + always @(posedge CLK) COP_DONE <= COP_GO; + +endmodule + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// 7. ex_dram_emul DRAM Emulator +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +module ex_dram_emul ( MCLK, RST_N, IC_ACC, IDRAM_ADR, DC_ACC, DC_WR, DRAM_ADR, DRAM_DI, + IC_MDONE, DC_MDONE, ENWR, WAMUX, WADDR, MEM_Q, IWCTRL, DWCTRL ); + +input MCLK; +input RST_N; +input IC_ACC; +input [27:0] IDRAM_ADR; +input DC_ACC; +input DC_WR; +input [27:0] DRAM_ADR; +input [35:0] DRAM_DI; + +output reg IC_MDONE; +output reg DC_MDONE; +output ENWR; +output reg WAMUX; +output [11:2] WADDR; +output reg [2:0] IWCTRL; +output reg [2:0] DWCTRL; + +output reg [31:0] MEM_Q; + +// +++++++++++++++++++ Memories ++++++++++++++++++++ + +parameter addr_msb = 13; // total memory is 16 kBytes + +reg [31:0] EDRAM [0:2**(addr_msb-1)-1]; +reg [addr_msb+34:0] FIFO [0:15]; + +reg [addr_msb+34:0] fifo_q; +reg [1:0] state; +reg [1:0] nibble,lsb; +reg [addr_msb:4] addr; +reg use_cache; +reg select; +reg [3:0] w_poi,r_poi,r_zeiger; +reg wr_next; + +wire [7:0] din_0,din_1,din_2,din_3; +wire [addr_msb:2] raddr; +wire frei; +wire start; +wire wr_req; +wire ca_req; +wire write; + +// +++++++++++++++++++++++++ Datapath +++++++++++++++++++ + + always @(negedge MCLK) if (DC_WR) FIFO[w_poi] <= {DRAM_ADR[addr_msb:2],DRAM_DI}; + + always @(posedge MCLK or negedge RST_N) + if (!RST_N) w_poi <= 4'd0; + else w_poi <= w_poi + {3'd0,DC_WR}; + + always @(posedge MCLK or negedge RST_N) + if (!RST_N) r_poi <= 4'd0; + else r_poi <= r_poi + {3'd0,write}; + + always @(negedge MCLK or negedge RST_N) + if (!RST_N) r_zeiger <= 4'd0; + else r_zeiger <= r_zeiger + {3'd0,write}; + + always @(posedge MCLK) fifo_q <= FIFO[r_zeiger]; + + always @(negedge MCLK) MEM_Q <= EDRAM[raddr]; // READ on falling edge + + assign din_0 = fifo_q[32] ? fifo_q[7:0] : MEM_Q[7:0]; + assign din_1 = fifo_q[33] ? fifo_q[15:8] : MEM_Q[15:8]; + assign din_2 = fifo_q[34] ? fifo_q[23:16] : MEM_Q[23:16]; + assign din_3 = fifo_q[35] ? fifo_q[31:24] : MEM_Q[31:24]; + + always @(posedge MCLK) if (write) EDRAM[raddr] <= {din_3,din_2,din_1,din_0}; // WRITE on rising edge + +// +++++++++++++++++++++++++ Controllogic +++++++++++++++++++ + + assign ca_req = DC_ACC | IC_ACC; // Cache Read Request + assign wr_req = (w_poi != r_poi); // Write Request + + assign write = (wr_req & ~ca_req & frei) | wr_next; + + always @(posedge MCLK or negedge RST_N) + if (!RST_N) wr_next <= 1'b0; + else wr_next <= write & (w_poi != (r_poi + 4'd1)); + + always @(posedge MCLK or negedge RST_N) + if (!RST_N) state <= 2'd0; + else + if (frei) state <= (ca_req & ~wr_next) ? 2'b01 : 2'd0; + else state <= state + 2'b01; + + assign frei = (state == 2'd0); + + assign start = ca_req & frei & ~wr_next; + + always @(negedge MCLK) + if (start) + begin + addr <= DC_ACC ? DRAM_ADR[addr_msb:4] : IDRAM_ADR[addr_msb:4]; + use_cache <= DC_ACC ? DRAM_ADR[1] : IDRAM_ADR[1]; + select <= DC_ACC; + end + + always @(negedge MCLK) + if (start) nibble <= DC_ACC ? {DRAM_ADR[3],~DRAM_ADR[2]} : {IDRAM_ADR[3],~IDRAM_ADR[2]}; + else + if (state == 2'b01) nibble <= {~nibble[1],1'b0}; + else + if (state[1]) nibble <= {nibble[1],~nibble[0]}; + + assign raddr = write ? fifo_q[addr_msb+34:36] : (start ? (DC_ACC ? DRAM_ADR[addr_msb:2] : IDRAM_ADR[addr_msb:2]) : {addr,nibble}); + + always @(negedge MCLK) lsb <= raddr[3:2]; + + assign ENWR = 1'b1; // always active + + always @(posedge MCLK) + begin + WAMUX <= start | ~frei; + + DC_MDONE <= select & (state == 2'b01); + DWCTRL[2] <= select & start; + DWCTRL[1] <= select & (start | ~frei) & use_cache; + DWCTRL[0] <= select & ~use_cache; + + IC_MDONE <= ~select & (state == 2'b10); // must be late to cover all cases + IWCTRL[2] <= ~select & start; + IWCTRL[1] <= ~select & (start | ~frei) & use_cache; + IWCTRL[0] <= ~select & ~use_cache; + end + + assign WADDR = {addr[11:4],lsb}; + +endmodule