Compare commits

..

No commits in common. "main" and "October-2025-Update" have entirely different histories.

14 changed files with 99 additions and 652 deletions

View file

@ -81,7 +81,7 @@ on the emulator image.
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.5/files/12) (source and windows binary)
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.4/files/16) for the Arty-A7-35T board
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.3/files/15) for the Arty-A7-35T board
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.4/files/13)
Contact the author here: tridoracpu [at] insignificance.de

View file

@ -1,5 +0,0 @@
const FIREWIDTH = 319; FIREHEIGHT = 79; (* keep in sync with fastfire.s! *)
type FireBuf = array [0..FIREHEIGHT, 0..FIREWIDTH] of integer;
procedure FastFireUpdate(var f:FireBuf); external;
procedure FastFireDraw(var f:FireBuf;screenx, screeny:integer); external;

View file

@ -1,326 +0,0 @@
; width and height of the fire cell matrix
; Be sure to sync this with fastfire.inc!
.EQU FIREWIDTH 319
.EQU FIREHEIGHT 79
;
; The cell matrix actually has one column
; and one row more than FIREWIDTH and
; FIREHEIGHT to handle the negative
; X offsets when calculating new
; cell values.
; Likewise, there is one more row.
; So rows are processed from 0 to FIREHEIGHT - 2
; and columms from 1 to FIREWIDTH - 1.
; cells considered for calculating new
; value for cell O (reference cells):
; .....O......
; ....123.....
; .....4......
; args: pointer to fire cell buffer
.EQU FF_ROW_COUNT 0
.EQU FF_COL_COUNT 4
.EQU FF_ROW_OFFS 8
.EQU FF_OFFS1 12
.EQU FF_OFFS2 16
.EQU FF_OFFS3 20
.EQU FF_OFFS4 24
.EQU FF_CELL_PTR 28
.EQU FF_FS 32
FASTFIREUPDATE:
FPADJ -FF_FS
STORE FF_CELL_PTR
LOADC FIREHEIGHT-1
STORE FF_ROW_COUNT
; calculate offsets for reference cells
LOADC FIREWIDTH+1
SHL 2
DUP
STORE FF_ROW_OFFS ; offset to next row: WIDTH*4
DEC 4 ; offset to cell 1: row offset - 4
DUP
STORE FF_OFFS1
INC 4
DUP
STORE FF_OFFS2 ; offset to cell 2: + 4
INC 4
STORE FF_OFFS3 ; offset to cell 3: + 4
LOAD FF_ROW_OFFS
SHL 1 ; offset to cell 4: row offset * 2
STORE FF_OFFS4
; start at column 1
LOAD FF_CELL_PTR
INC 4
STORE FF_CELL_PTR
FF_ROW:
LOADC FIREWIDTH-1
STORE FF_COL_COUNT
FF_COL:
LOAD FF_CELL_PTR
LOAD FF_OFFS1
ADD
LOADI
LOAD FF_CELL_PTR
LOAD FF_OFFS2
ADD
LOADI
LOAD FF_CELL_PTR
LOAD FF_OFFS3
ADD
LOADI
LOAD FF_CELL_PTR
LOAD FF_OFFS4
ADD
LOADI
ADD
ADD
ADD
SHR
SHR
; if new cell value > 0, subtract 1 to cool down
DUP
CBRANCH.Z FF_SKIP
DEC 1
FF_SKIP:
LOAD FF_CELL_PTR ; load cell ptr
SWAP ; swap with new value
STOREI 4 ; store with postincrement
STORE FF_CELL_PTR ; save new ptr value
LOAD FF_COL_COUNT ; decrement column count
DEC 1
DUP
STORE FF_COL_COUNT
CBRANCH.NZ FF_COL ; loop if col count <> 0
; at the end of a row, go to next row
; by adding 8 to the cell pointer,
; skipping the first cell of the next row
LOAD FF_CELL_PTR
INC 8
STORE FF_CELL_PTR
LOAD FF_ROW_COUNT ; decrement row count
DEC 1
DUP
STORE FF_ROW_COUNT
CBRANCH.NZ FF_ROW ; loop if row count <> 0
FF_EXIT:
FPADJ FF_FS
RET
; framebuffer controller registers
.EQU FB_RA $900
.EQU FB_WA $901
.EQU FB_IO $902
.EQU FB_PS $903
.EQU FB_PD $904
.EQU FB_CTL $905
.EQU WORDS_PER_LINE 80
; fire width in vmem words (strict left-to-right evaluation)
.EQU FFD_ROW_WORDS 1 + FIREWIDTH / 8
; draw all fire cells
; args: pointer to fire cell buffer, screen x, screen y
.EQU FFD_CELL_PTR 0
.EQU FFD_X 4
.EQU FFD_Y 8
.EQU FFD_ROW_COUNT 12
.EQU FFD_ROW_WORDCOUNT 16
.EQU FFD_VMEM_PTR 20
.EQU FFD_FS 24
FASTFIREDRAW:
FPADJ -FFD_FS
STORE FFD_Y
STORE FFD_X
STORE FFD_CELL_PTR
; calculate video memory addr
; addr = y * 80 + X / 8
LOAD FFD_Y
SHL 2 ; y * 16
SHL 2
DUP
SHL 2 ; + y * 64
ADD ; = y * 80
LOAD FFD_X
SHR
SHR
SHR
ADD ; + x / 8
DUP
STORE FFD_VMEM_PTR
LOADC FB_WA ; set vmem write address
SWAP
STOREI
DROP
LOADC FIREHEIGHT + 1
STORE FFD_ROW_COUNT
FFD_ROW:
LOADC FFD_ROW_WORDS
STORE FFD_ROW_WORDCOUNT
LOADC FB_WA ; set vmem write address
LOAD FFD_VMEM_PTR
STOREI
DROP
FFD_WORD:
LOAD FFD_CELL_PTR ; load cell ptr
LOADC 0 ; vmem word, start with 0
; leftmost pixel (0)
OVER ; [ cptr, vmemw, cptr ]
LOADI ; load cell value [ cptr, vmemw, cellval ]
SHR ; scale it down (from 7 bits to 4)
SHR
SHR ; [ cptr, vmemw, cellval shr 3 ]
OR ; [ cptr, vmemw ]
SWAP ; [ vmemw, cptr ]
INC 4 ; increment cell ptr on stack [ vmemw, cptr + 4 ]
SWAP ; [ cptr + 4, vmemw ]
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 1
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 2
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 3
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 4
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 5
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 6
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
SHL 2 ; move bits to left for next pixel
SHL 2
; pixel 7
OVER
LOADI ; load cell value
SHR ; scale it down (from 7 bits to 4)
SHR
SHR
OR
SWAP
INC 4 ; increment cell ptr on stack
SWAP
; store word to vmem
; vmem write addr will autoincrement
LOADC FB_IO
SWAP
STOREI
DROP
STORE FFD_CELL_PTR
; prepare for next word
LOAD FFD_ROW_WORDCOUNT
DEC 1
DUP
STORE FFD_ROW_WORDCOUNT
CBRANCH.NZ FFD_WORD
; prepare for next row
LOAD FFD_VMEM_PTR
LOADC WORDS_PER_LINE
ADD
STORE FFD_VMEM_PTR
LOAD FFD_ROW_COUNT
DEC 1
DUP
STORE FFD_ROW_COUNT
CBRANCH.NZ FFD_ROW
FFD_EXIT:
FPADJ FFD_FS
RET

View file

@ -1,76 +0,0 @@
{$H1}
{$S2}
program fire;
const MAXX = 30;
MAXY = 50;
var firebuf: array [0..MAXY, 0..MAXX] of integer;
firepalette: array [0..15] of integer =
( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
$F00, $E00, $D00, $A00, $800, $600, $300, $000);
x,y:integer;
procedure createPalette;
var i:integer;
begin
for i := 15 downto 0 do
setpalette(15 - i, firepalette[i]);
end;
procedure fireItUp;
var x,y:integer;
begin
y := MAXY - 1;
for x := 1 to MAXX - 1 do
firebuf[y, x] := random and 127;
end;
procedure updateFire;
var i,x,y:integer;
begin
for y := 0 to MAXY - 2 do
for x := 1 to MAXX - 1 do
begin
i :=
((firebuf[y + 1, x - 1]
+ firebuf[y + 1, x]
+ firebuf[y + 1, x + 1]
+ firebuf[y + 2, x])
) shr 2;
if i > 0 then
i := i - 1;
firebuf[y, x] := i;
end;
end;
procedure drawFire;
var x, y, col:integer;
begin
for y := 0 to MAXY - 1 do
begin
x := 0;
for col in firebuf[y] do
begin
putpixel(300 + x, 150 + y, col shr 3);
x := x + 1;
end;
end;
end;
begin
randomize;
initgraphics;
createPalette;
while not conavail do
begin
fireItUp;
updateFire;
drawFire;
end;
for y := 0 to MAXY do
begin
x := firebuf[y, 10];
drawline(0, y, x, y, 1);
end;
end.

View file

@ -1,84 +0,0 @@
{$H1}
{$S1}
program fire2;
uses fastfire;
const MAXX = FIREWIDTH;
MAXY = FIREHEIGHT;
var firecells: FireBuf;
firepalette: array [0..15] of integer =
{ ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
$F00, $E00, $D00, $A00, $800, $600, $300, $000); }
( $FFA, $FFA, $FFA, $FFA, $FF0, $FF0, $FF0, $FF0,
$FF0, $FD0, $FA0, $C00, $A00, $700, $400, $000);
x,y:integer;
procedure createPalette;
var i:integer;
begin
for i := 15 downto 0 do
setpalette(15 - i, firepalette[i]);
end;
procedure fireItUp;
var x,y:integer;
begin
y := MAXY - 1;
for x := 1 to MAXX - 1 do
firecells[y, x] := random and 127;
end;
procedure updateFire;
var i,x,y:integer;
begin
for y := 0 to MAXY - 2 do
for x := 1 to MAXX - 1 do
begin
i :=
((firecells[y + 1, x - 1]
+ firecells[y + 1, x]
+ firecells[y + 1, x + 1]
+ firecells[y + 2, x])
) shr 2;
if i > 0 then
i := i - 1;
firecells[y, x] := i;
end;
end;
procedure drawFire;
var x, y, col:integer;
begin
for y := 0 to MAXY - 1 do
begin
x := 0;
for col in firecells[y] do
begin
putpixel(100 + x, 150 + y, col shr 3);
x := x + 1;
end;
end;
end;
begin
randomize;
initgraphics;
createPalette;
while not conavail do
begin
fireItUp;
FastFireUpdate(firecells);
{ updateFire; }
FastFireDraw(firecells, 160, 100);
{ drawFire; }
end;
for y := 0 to MAXY do
begin
x := firecells[y, 10];
drawline(0, y, x, y, 1);
end;
end.

View file

@ -324,9 +324,7 @@ begin
rewindStringList(usedUnits);
while nextStringListItem(usedUnits, unitName) do
emitInclude(unitName + UnitSuffix2);
(* _END label needs to be word-aligned because
it is used as the start of the heap *)
emitIns('.ALIGN');
emitLabelRaw('_END');
end;

View file

@ -2056,9 +2056,6 @@ begin
operandValue := 0;
emitBlock(count, operandValue);
end
else
if lastToken.tokenText = '.ALIGN' then
alignOutput(wordSize)
else
errorExit2('Unrecognized directive', lastToken.tokenText);
end;

View file

@ -226,7 +226,6 @@ begin
if not invalid then
begin
open(xferFile, filename, ModeOverwrite);
blockNo := 0;
done := false;
repeat
serReadBlock(ok);

View file

@ -8,8 +8,8 @@ set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
## Switches
#set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
#set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
@ -34,7 +34,7 @@ set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2]
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
## Buttons
#set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]

View file

@ -16,9 +16,9 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
output wire write_enable,
input wire mem_wait,
output wire debug1,
output wire debug2,
output wire debug3
output wire led1,
output wire led2,
output wire led3
);
localparam EVAL_STACK_INDEX_WIDTH = 6;
@ -90,6 +90,7 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
wire mem_write;
wire x_is_zero;
// wire [WIDTH-1:0] y_plus_operand = Y + operand;
wire x_equals_y = X == Y;
wire y_lessthan_x = $signed(Y) < $signed(X);
@ -104,10 +105,16 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
assign write_enable = mem_write_enable;
// debug output ------------------------------------------------------------------------------------
assign debug1 = reset;
assign debug2 = ins_loadc;
assign debug3 = ins_branch;
assign led1 = reset;
assign led2 = ins_loadc;
assign led3 = ins_branch;
// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero,
// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state};
// assign debug_out2 = data_in;
// assign debug_out3 = nX;
// assign debug_out4 = nPC;
// assign debug_out5 = ins;
// assign debug_out6 = IV;
//--------------------------------------------------------------------------------------------------
// instruction decoding

View file

@ -7,7 +7,7 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
input wire reset,
input wire [1:0] reg_sel,
output wire [DATA_WIDTH-1:0] rd_data,
input wire [AMP_WIDTH-1:0] wr_data,
input wire [DATA_WIDTH-1:0] wr_data,
input wire rd_en,
input wire wr_en,
@ -20,9 +20,6 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
localparam TDRAU_REG_CLK = 1; /* clock divider register */
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
/* avoid warning about unconnected port */
(* keep="soft" *) wire _unused = rd_en;
reg channel_enable;
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
reg [CLOCK_DIV_WIDTH-1:0] div_count;
@ -32,12 +29,12 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
wire fifo_wr_en;
wire fifo_rd_en, fifo_full, fifo_empty;
wire [AMP_WIDTH-1:0] fifo_rd_data;
wire [DATA_WIDTH-1:0] fifo_rd_data;
fifo #(.ADDR_WIDTH(4), .DATA_WIDTH(16)) sample_buf(
clk, reset,
fifo_wr_en, fifo_rd_en,
wr_data[AMP_WIDTH-1:0], fifo_rd_data,
wr_data, fifo_rd_data,
fifo_full,
fifo_empty
);
@ -169,14 +166,9 @@ module tdraudio #(DATA_WIDTH=32) (
localparam AMP_BIAS = 32768;
localparam DAC_WIDTH = 18;
/* avoid warning about unconnected port */
(* keep="soft" *) wire [DATA_WIDTH-1:AMP_WIDTH] _unused = wr_data[DATA_WIDTH-1:AMP_WIDTH];
wire [4:0] chan_sel = io_addr[6:2];
wire [1:0] reg_sel = io_addr[1:0];
wire [AMP_WIDTH-1:0] amp_wr_data = wr_data[AMP_WIDTH-1:0];
wire [AMP_WIDTH-1:0] chan0_amp;
wire [DATA_WIDTH-1:0] chan0_rd_data;
wire chan0_running;
@ -218,25 +210,25 @@ module tdraudio #(DATA_WIDTH=32) (
{DATA_WIDTH{1'b1}};
wavegen chan0(clk, reset, reg_sel,
chan0_rd_data, amp_wr_data,
chan0_rd_data, wr_data,
chan0_rd_en, chan0_wr_en,
chan0_amp,
chan0_running, chan0_irq);
wavegen chan1(clk, reset, reg_sel,
chan1_rd_data, amp_wr_data,
chan1_rd_data, wr_data,
chan1_rd_en, chan1_wr_en,
chan1_amp,
chan1_running, chan1_irq);
wavegen chan2(clk, reset, reg_sel,
chan2_rd_data, amp_wr_data,
chan2_rd_data, wr_data,
chan2_rd_en, chan2_wr_en,
chan2_amp,
chan2_irq, chan2_running);
wavegen chan3(clk, reset, reg_sel,
chan3_rd_data, amp_wr_data,
chan3_rd_data, wr_data,
chan3_rd_en, chan3_wr_en,
chan3_amp,
chan3_running, chan3_irq);

View file

@ -15,6 +15,9 @@
module top(
input wire clk,
input wire rst,
input wire btn0,
input wire sw0,
input wire sw1,
output wire led0,
output wire led1,
output wire led2,
@ -226,15 +229,6 @@ module top(
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
wire audio_irq;
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
uart_baud,
uart_txd_in, uart_rxd_out,
uart_rx_clear, uart_tx_en,
uart_rx_avail, uart_tx_busy,
uart_tx_data, uart_rx_data);
// audio controller
`ifdef ENABLE_TDRAUDIO
wire [WIDTH-1:0] tdraudio_wr_data;
wire [WIDTH-1:0] tdraudio_rd_data;
@ -279,6 +273,13 @@ module top(
`endif
-1;
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
uart_baud,
uart_txd_in, uart_rxd_out,
uart_rx_clear, uart_tx_en,
uart_rx_avail, uart_tx_busy,
uart_tx_data, uart_rx_data);
// CPU -----------------------------------------------------------------
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
.addr(mem_addr),
@ -286,7 +287,7 @@ module top(
.read_ins(dram_read_ins),
.data_out(mem_write_data), .write_enable(mem_write_enable),
.mem_wait(mem_wait),
.debug1(led1), .debug2(led2), .debug3(led3));
.led1(led1), .led2(led2), .led3(led3));
// Interrupt Controller
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,

View file

@ -378,19 +378,30 @@
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024">
<Desc>Default settings for Implementation.</Desc>
<StratHandle Name="Performance_ExploreWithRemap" Flow="Vivado Implementation 2024">
<Desc>Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="opt_design">
<Option Id="Directive">6</Option>
</Step>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="place_design">
<Option Id="Directive">0</Option>
</Step>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="phys_opt_design">
<Option Id="Directive">0</Option>
</Step>
<Step Id="route_design">
<Option Id="Directive">1</Option>
<Option Id="MoreOptsStr"><![CDATA[-tns_cleanup]]></Option>
</Step>
<Step Id="post_route_phys_opt_design" EnableStepBool="1">
<Option Id="Directive">0</Option>
</Step>
<Step Id="write_bitstream">
<Option Id="BinFile">1</Option>
</Step>

View file

@ -16,7 +16,6 @@
# limitations under the License.
import sys
import os
import serial
import time
import random
@ -42,6 +41,30 @@ def get_default_device():
return '/dev/ttyUSB1'
def serwrite_slow(databytes, ser):
total = len(data)
count = 1
for d in data:
sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
ser.write(bytes(d,"utf8"))
count += 1
time.sleep(0.020)
print()
def serwrite(datafile, ser):
with open(datafile) as f:
data = f.read()
total = len(data)
count = 1
for d in data:
sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
ser.write(bytes(d,"utf8"))
count += 1
time.sleep(0.020)
print()
def checksum(databytes):
i = 0
cksum = 0
@ -62,29 +85,13 @@ def sendchar(char, ser):
ser.write(char.to_bytes(1, 'big'))
def sendcommand(ser, cmd=b'L', verbose=False):
verbose = True
def sendcommand(ser, cmd=b'L'):
ser.write(cmd)
resp = ser.read_until()
if verbose:
print(cmd,"sent, response:", str(resp))
return resp
# send command and wait for echo
def commandwait(ser, cmd):
resp = sendcommand(ser, cmd, verbose=False)
if len(resp) == 0:
print("timeout sending '{}' command".format(cmd))
return None
if resp != bytearray(cmd + b"\r\n"):
print("invalid response to '{}' command".format(cmd))
return None
return resp
def send_size_header(ser, filesize):
ser.write(b'\x05') # ENQ
resp = ser.read(1)
@ -146,8 +153,6 @@ def serload_bin(datafile, ser):
data += bytearray(pad)
print("{} total blocks".format((len(data) + blocksize - 1) // blocksize))
if not send_size_header(ser, filesize):
print("Error sending size header.")
return
@ -274,8 +279,18 @@ def serdownload(fname, ser):
def mput(filenames, ser):
for f in filenames:
resp = set_filename(f, ser)
if resp is None:
f_encoded = f.encode('utf8')
print("Setting filename", f)
resp = sendcommand(ser, b'S')
if len(resp) == 0:
print("timeout sending 'S' command")
return
if resp != b'S\r\n' and resp != b'> S\r\n':
print("unrecognized response to 'S' command, aborting")
return
resp = sendcommand(ser, f_encoded + b'\r')
if not f_encoded in resp:
print("unrecognized response to filename, aborting")
return
serload_bin(f, ser)
@ -284,92 +299,12 @@ def mput(filenames, ser):
time.sleep(2)
def set_filename(f, ser):
f_encoded = f.encode('utf8')
print("Setting filename", f)
resp = commandwait(ser, b'S')
if resp is None:
return None
resp = sendcommand(ser, f_encoded + b'\r')
if not f_encoded in resp:
print("unrecognized response to filename, aborting")
return None
return resp
def getnamedfile(filename, ser):
resp = set_filename(filename, ser)
if resp is None:
return None
serdownload(filename, ser)
def putnamedfile(filename, ser):
resp = set_filename(filename, ser)
if resp is None:
return None
serload_bin(filename, ser)
print("Remote status:")
showdata(ser)
def showdata(ser):
promptseen = False
while not promptseen:
c = ser.read(1)
if c == b'>':
promptseen = True
else:
print(c.decode('utf8'), end='')
rest = ser.read(1)
def localdir():
result = os.walk(".")
for dirpath, dirnames, filenames in os.walk("."):
for f in filenames:
print(f)
break
def interactive(ser):
done = False
while not done:
args = input("> ").strip().split()
if len(args) > 0:
cmd = args[0]
args.pop(0)
if cmd == 'dir':
if commandwait(ser, b'Y') is None:
return
showdata(ser)
elif cmd == 'get':
if len(args) > 1:
print("exactly one argument required (filename)")
else:
getnamedfile(args[0], ser)
elif cmd == 'put':
if len(args) > 1:
print("exactly one argument required (filename)")
else:
putnamedfile(args[0], ser)
elif cmd == 'ldir':
if len(args) > 0:
print("superfluous argument")
else:
localdir()
else:
print("Unknown command. Valid commands are: dir get ldir put")
if __name__ == "__main__":
argparser = argparse.ArgumentParser(
description='transfer files from/to the Tridora-CPU')
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
argparser.add_argument('command', choices=['get', 'put', 'mput', 'interactive'])
argparser.add_argument('filename', nargs='*')
argparser.add_argument('command', choices=['get', 'put', 'mput'])
argparser.add_argument('filename', nargs='+')
args = argparser.parse_args()
cmd = args.command
@ -384,10 +319,8 @@ if __name__ == "__main__":
serload_bin(filenames[0], ser)
elif cmd == 'mput':
mput(filenames, ser)
elif cmd == 'interactive':
interactive(ser)
else:
print("should not get here")
#if cmd is not None:
# ser.close()
if cmd is not None:
ser.close()