Git Product home page Git Product logo

opbasm's Introduction

http://kevinpt.github.io/opbasm/_static/opbasm_logo.png

Open PicoBlaze Assembler

Opbasm is a free cross-platform assembler for the PicoBlaze-3 (PB3) and PicoBlaze-6 (PB6) microcontrollers provided by Xilinx. It will run readily on any platform with a Python interpreter. Opbasm provides a better performing solution to assembling PicoBlaze code without resorting to DOS or Windows emulation to run the native KCPSM assemblers.

Special features of Opbasm:

  • Optional m4 preprocessor macros are available when the m4 program is installed. An extensive set of built-in macros provide more advanced features than the base language. For example, converting temperature scales becomes as easy as this:
reg16(rx, s4,s5)                ; Create a virtual 16-bit register pair named rx

c_to_f:
  load reglower(rx), s0         ; Load 8-bit Celsius temperature into low byte
  signex(rx)                    ; Sign extend to 16-bits
  expr2s(rx := rx * 9 / 5 + 32) ; Perform 16x8-bit signed arithmetic to get Fahrenheit
  return

Support for the full PicoBlaze-6 syntax is provided as well as enabling most of the new PB6 syntax enhancements in PicoBlaze-3 code. The original templating system for ROM components is supported as well as a more flexible generic ROM component that can read .mem and .hex files directly during synthesis and simulation. A utility script is included that permits updating the ROM contents of a bitstream file without requiring resynthesis as was formerly supplied by the DOS-based KCPSM3 tools.

Files generated on non-Windows platforms will not have DOS line endings and PicoBlaze-3 files are not restricted to 8.3 file names. Opbasm also runs significantly faster than the native implementation:

http://kevinpt.github.io/opbasm/_images/opbasm_perf.png

Requirements

Opbasm requires Python 3.x and no additional libraries. The installation script depends on setuptools which will be installed if it isn't currently present in your Python distribution. Optional macro support is provided when m4 is installed. You can get optional colorized output from the scripts by installing the Python colorama package.

Download

You can access the Opbasm Git repository from Github. Packaged source code is also available for download. You can install direct from PyPI with the "pip" command if you have it available.

Installation

You can use pip to get the latest development code from Github:

> pip install --upgrade https://github.com/kevinpt/opbasm/tarball/master

If you manually downloaded a source package or created a clone with Git you can install Opbasm with the following command run from the base Opbasm directory:

> python setup.py install

On Linux systems you may need to install with root privileges using the sudo command.

After a successful install the Opbasm scripts will be available. On Linux they should be immediately accessible from your current search path. On Windows you will need to make sure that the <Python root>\Scripts directory is in your %PATH% environment variable.

Documentation

The full documentation is available online at the main Opbasm site.

opbasm's People

Contributors

kevinpt avatar paebbels avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opbasm's Issues

opbasm 1.1 with --pyparsing can't read windows formatted paths in INCLUDE

I'm using opbasm 1.1 from HG repository Rev. 53 (379e9b667a51) 29.08.2014.
This is a followup issue to Google code issue 3.

I tried to solve issue 3 by enabling the old parser with --pyparsing.
This solves the relative path / interpreting paths as instruction problem, but 
this mode allows path only to have linux style ("/" delimited).

Is it possible to allow both common path separators ("/" or "\") maybe as an 
additional command line option?

In this case I would be able to use the same source files on windows (with 
KCPSM6.exe or opbasm) and Linux (only opbasm).

Original issue reported on code.google.com by Paebbels on 8 Oct 2014 at 6:16

Error in index_expanded_line_numbers()

Tried to use m4 and it bombs on line 792. I first tried a normal .psm file with the --m4 option, failed. Then I tried it on load.psm4 in the .\test\asm directory, failed. Problem(s) are that active_file = None and source_lines = {}.

Traceback (most recent call last):
File "C:\Tools\opbasm-1.3\opbasm.py", line 2530, in
main()
File "C:\Tools\opbasm-1.3\opbasm.py", line 2381, in main
for fname in asm.process_includes():
File "C:\Tools\opbasm-1.3\opbasm.py", line 810, in process_includes
pp_source_file = self.preprocess_with_m4(source_file)
File "C:\Tools\opbasm-1.3\opbasm.py", line 687, in preprocess_with_m4
self.index_expanded_line_numbers(m4_result, pp_source_file, source_file)
File "C:\Tools\opbasm-1.3\opbasm.py", line 792, in index_expanded_line_numbers
index.append((cur_line, source_lines[active_file], active_file))
KeyError: None

defining constants with evalh/d fails

The following code (from the manual) fails

constant cname, evalh(20 + 6)

Error message:

m4:stdin:25: ERROR: end of file in argument list

The same happens when using evald instead of evalh. Using eval works, but produces the wrong result, obviously.

m4 (GNU M4) 1.4.17
OPBASM version 1.3.3

Using PUSH and POP from an INCLUDEd file doesn't work

I'm calling use_stack from top level file that includes multiple other files with subroutines. Those routines use stack operations like PUSH and POP to save registers. When I try to assemble I'm getting the error:

Stack is not initialized. Use use_stack() before any operation  stdin line 7
ERROR: m4 failure on file serial.psm

It seems to me like M4 pre-processor is ran on included files before the top file, so it doesn't recognize that I'm setting up the stack in in the top file. How can I reorganize my code so that I can use stack macros and still have it split up in multiple files? Is this an issue with macros or am I doing something wrong?

My code looks like this:

; program.psm:
namereg s3, SP      ; Protect s3 for use as the stack pointer
use_stack(SP, 0x3F) ; Start stack at end of 64-byte scratchpad

INCLUDE "subroutines.psm"
;subroutines.psm:
foo:
       PUSH(s7,s6)
       ...  
       POP(s7,s6)
       RETURN

EDIT:
I'm working around it by adding use_stack at the top of all included files, not sure if that's actually a good idea, but it works.

Writing "label :" will cause opbasm to not define the label as expected

Example broken code:

label : or s0, s0
call label

Output from latest master:

ยป opbasm -m 1024 -3 --verbose wat.psm
OPBASM - Open PicoBlaze Assembler 1.3.9
Target architecture: PicoBlaze-3
  Device configuration:
    Memory size: 1024, Scratchpad size: 64

  Reading source: wat.psm

  Assembling code...

ERROR: Invalid address: label
  wat.psm line 2:  call label

Escape codes for terminal colors are printed literal

Example output:

rother@server:~/psm$ opbasm -3 -i test.psm4 --verbose
b'\x1b[35mOPBASM - Open PicoBlaze Assembler 1.3.9\x1b[0m'
b'\x1b[35mTarget architecture: \x1b[0m\x1b[32mPicoBlaze-3\x1b[0m'

This used to work in older versions, where the text was actually colorized.

Create a new OPBASM release

The code in the repository contains many fixes which are not available in the installation from PyPI.

E.g. m4 isn't found on Windows system due to missing double quotes for C:\Program Files\.... This is fixed OPBASMs sources in GitHub, but not yet published. Latest release is from December 2015, while code is from March 2019.

Please push a new release to PyPI.

I you like, I can provide a GitHub Workflow description to release tagged versions automatically to PyPI on every (tagged) push.

Call opbasm directly in Python instead of the command line

Hello,

Thanks a lot for the great work and great documentation!
I wrote a simple Python program that compiles a psm code, loads it in a BRAM shared with the Picoblaze and run the Picoblaze. 100 iterations take only 2.5 seconds !

Could you advise on a simple way to use opbasm directly from Python (from opbasm import ...) instead of calling the command line ?

Thanks,
Jean

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from koheron import connect, command
import os
import subprocess

class Picoblaze(object):
    def __init__(self, client):
        self.client = client

    @command()
    def write_ram(self, address, value):
        pass

    @command()
    def reset(self):
        pass

    @command()
    def set_input(self, value):
        pass

    @command()
    def get_output(self):
        return self.client.recv_uint32()

host = os.getenv('HOST','10.42.0.201')
client = connect(host, name='picoblaze')
driver = Picoblaze(client)

code = """
input s0, 0
add s0, {:x}
output s0, 0
"""

for i in range(100):

    with open("test.psm", "w") as f:
        f.write(code.format(i))

    # Compile test.psm with opbasm
    subprocess.call(['opbasm', '--pb6', '--scratch-size=64', '--hex', '--mem-size=32', '--quiet', 'test.psm'])

    # Write program to BRAM
    with open('test.hex', 'r') as f:
        for j, line in enumerate(f):
            driver.write_ram(4*j, (int(line, 16)))

    driver.set_input(2)
    driver.reset() # Restart picoblaze
    print i, driver.get_output()
    assert(driver.get_output() == 2 + i)

-o flags produces an entity name with path in the rom code

if -o ( --outdir ) flag is used, the entity name of the generated vhdl rom code has the entity name with the used path in the command line flag ::
opbasm -c -x --m4 -6 -i hello.psm --outdir=/path/to/vhdl/sources/ -n rom -t template.vhdl

produces an output such this::

entity /path/to/vhdl/sources/rom is
  generic(             C_FAMILY : string := "S6"; 
              C_RAM_SIZE_KWORDS : integer := 1;
           C_JTAG_LOADER_ENABLE : integer := 0);
  Port (      address : in std_logic_vector(11 downto 0);
          instruction : out std_logic_vector(17 downto 0);
               enable : in std_logic;
                  rdl : out std_logic;                    
                  clk : in std_logic);
  end /path/to/vhdl/sources/rom;

Add support for negated tests

Currently it is not possible to negate a test in a C-style if, so one has to fall back to ugly constructs like this:

if (sA & FC_MEM_RX_FC_FCCS_VALID_BIT) {
} else {
	jump respinv_end
}

It would be nice if there were a not() modifier for the condition (like signed()), or maybe a ~& operator or the like.

(Side note: Sorry for opening so many issue, I just started using optasm for my master thesis, and this are just the things I came across, which I thought might be useful in general ๐Ÿ˜„ . optasm is awesome!)

local labels do not work when using C-style ifs

The following code does not work:

proc:
jump .test
if (sA == 1) {
  nop()
}
.test:
nop()

This is because the if will create a label that will destroy the locality of .local. It would be nice if automatic generated labels could be ignored while parsing local label. This would make this features much more useful.

Nested for loops run infinitely

* What steps will reproduce the problem?

NAMEREG s1, LOOP_R
NAMEREG s2, IN_LOOP_R
  LOAD s3, 32
  for( LOOP_R := 0, LOOP_R != s3, LOOP_R := LOOP_R + 1 ) {
    for( IN_LOOP_R := 0, IN_LOOP_R != 1, IN_LOOP_R := IN_LOOP_R + 1, `
      OUTPUT   IN_LOOP_R, 01
    ')
  }


* What is the expected output? What do you see instead?
Expected generated output:

; Expression: LOOP_R := 0
load LOOP_R, 00

FOR_f1_0038:
; If LOOP_R != s3
compare LOOP_R, s3
jump z, EQ_f1_0041

; Expression: IN_LOOP_R := 0
load IN_LOOP_R, 00


FOR_f1_0043:
; If IN_LOOP_R != 1
compare IN_LOOP_R, 01
jump z, EQ_f1_0046

  OUTPUT   IN_LOOP_R, 01

NEXTFOR_f1_0044:                                        
; Expression: IN_LOOP_R := IN_LOOP_R + 1

add IN_LOOP_R, 01

jump FOR_f1_0043                                        

EQ_f1_0046:

ENDLOOP_f1_0045:

NEXTFOR_f1_0039: 
; Expression: LOOP_R := LOOP_R + 1 

add LOOP_R, 01

jump FOR_f1_0038    *******************

EQ_f1_0041:

ENDLOOP_f1_0040:

Instead of "jump FOR_f1_0038" we get "jump FOR_f1_0043" pointing back to the 
start of the inner loop and resulting in an infinite loop.


* What version of the product are you using? On what operating system?

opbasm 1.2 on Linux CentOS 6.6
2.6.32-504.16.2.el6.x86_64 #1 SMP Wed Apr 22 06:48:29 UTC 2015 x86_64 x86_64 
x86_64 GNU/Linux


* Please provide any additional information below.

This can be worked around by defining an extra "for_inner()" M4 macro that is 
identical to the existing M4 "for()" macro in "picoblaze.m4" but replacing the 
label names.  Note: `popdef(_slbl)' appears to be missing at the end of the for 
macro.

Original issue reported on code.google.com by [email protected] on 24 Apr 2015 at 12:09

KCPSM6.exe assembler log file compatibly

Hello again,

I wrote some python scripts to parse the KCPSM6.exe log file. In particular I 
annotated the source code with special comments to mark the beginning and 
ending of a subroutine.

;; function _lcd_writebyte
_lcd_writebyte:   LOAD Reg_Tmp0, Reg_Arg0
                  [...]
                  Return
;; end function

These lines also appear in the (formated) log file. KCPSM6.exe places the 
current instruction address in front of every line. Your opbasm prints this 
addresses only in front of real instructions.

Would it be possible to add the (next) instruction address in front of every 
log line for compatibly?

-----------
I use these 'function' - 'end function' markers to find the start and end 
address of subroutines, which I translate into a VHDL package as a simulation 
helper and into a token file as a chipscope helper.

See PicoBlaze Forum for more information on this topic:
http://forums.xilinx.com/t5/PicoBlaze/Contribution-of-PicoBlaze-add-ons/td-p/446
556

Original issue reported on code.google.com by Paebbels on 24 Jul 2014 at 6:02

Use simpler regex for matching C-style constructs

The current regex for matching a C-style if is if\s*\(([^)]*)\)(?:\s*;.*\n)*\s*{. This causes problems with code like if (regupper(rx) == 0) { because of additional parentheses. When using this following, simpler regex, this works without problems: if\s*\((.*)\)(?:\s*;.*\n)*\s*{.

Is there any specific reason for the first form of the regex? This method also removes the special handling for the signed() macro.

opbasm 1.1 interprets relative path as an assembler instruction

I'm using opbasm 1.1 from HG repository Rev. 53 (379e9b667a51) 29.08.2014.

If I'm using opbasm with the new parser (--pyparsing is not set; see Google 
code issue 4 for reference), it seems that all INCLUDE instructions with 
relative paths are tried to translate into real assembler instructions.

examples:

; this is ok
INCLUDE "SoFPGA_Texts.psm"
;
; this throws an error
INCLUDE "..\lib\L_PicoBlaze\psm\RegisterNames.psm"

The extracted and unknown instruction is "RegisterNames ". Note the trailing 
space before the quote sign.

Original issue reported on code.google.com by Paebbels on 8 Oct 2014 at 6:07

Expression evaluation is limited to a single constant

First of all I am relatively new to opbasm but I really like the already huge feature set.

As to my problem I have tried using multiple constants in an eval expression with the simple testcase below but unfortunately I stumbled across some problems.

constant foo, 55
constant bar, AA

load s0, evalh(foo)
load s1, evalh(bar)
load s2, evalh(0x55 | 0xAA)
load s3, evalh(foo | bar)
load s4, evalh(evalc(foo) | evalc(bar))

The code generated by m4 is:

constant foo, 55 
constant bar, AA 

load s0, 55  ; foo
load s1, aa  ; bar
load s2, ff  ; 0x55 | 0xAA
load s3,   ; foo | bar
load s4, ff  ; 85 | 170

with telling me:

m4:stdin:7: bad expression in eval (bad input): (foo | bar) & 0xFF
m4:stdin:8: empty string treated as 0 in builtin `eval'
m4:stdin:8: empty string treated as 0 in builtin `eval'

My expectation was that load s3, evalh(evalc(foo) | evalc(bar)) would be evaluated to load s3, ff.
I tried to workaround by using load s4, evalh(evalc(foo) | evalc(bar)) which actually resulted in the correct output but creates two warnings.
Are there any negative side effects on using this workaround beside the warnings?
Is there another macro that I should prefer?

Nevertheless supporting the syntax in line 7 would greatly increase readability of the code.

Error information format

When compile executes from VS Code if format is <file_name.psm>:<line_num> user can go to that line in editor by ctrl+click on name (main.PSM4 in example below)
current format

ERROR: Invalid PicoBlaze-3 instruction: <blah_blah>
  main.PSM4 line 195 (expanded line 251) 251:  <blah_blah>

I suggest changing the format:

ERROR: Invalid PicoBlaze-3 instruction: <blah_blah>
  main.PSM4:195 (expanded line 251) 251:  <blah_blah>

Installation of opbasm on Windows 7 x64, Python 3.4.x fails

Hi,

I successfully installed opbasm (current snapshot - c34137a2...a861bd66) on my 
linux machine (Debian, x64, python 3.4.x) all is working fine. After that I 
tried to install opbasm on my Windows machine (Windows7, x64, python 3.4.x) and 
got several errors. I'll number my paragraphs for a better reply.

(1)
By mistake I started setup.py with python2 (2.6.2) and found this error:
python setup.py install
[...]
Download error on https://pypi.python.org/simple/pyparsing/: unknown url type: 
https -- Some packages may not be found!
[...]
Download error on https://pypi.python.org/simple/: unknown url type: https -- 
Some packages may not be found!
[...]

(2)
After that I corrected my mistake and launched setup.py with python3:
py -3 setup.py install

There is a syntax error in opbasm.py at line 404:
[...]
byte-compiling build\bdist.win-amd64\egg\opbasm.py to opbasm.cpython-34.pyc
  File "build\bdist.win-amd64\egg\opbasm.py", line 404
    except ParseException, e:
                         ^
SyntaxError: invalid syntax
[...]

(3)
As I fixed line 404, I go an other syntax error at line 1444.

(4)
I also tried the provided installer package for windows. The installer was not 
able to detect my installed python versions (neither 2.6.2 nor 3.4.0). So I 
could only abort the installation.


Original issue reported on code.google.com by Paebbels on 21 Jul 2014 at 9:33

Function visibility

Compiler can't see function from another file.
main.psm4 file:

...
LOAD PARRAY,  03
LOAD ARR_CNT, 08;  
fn_spi_read_byte_array(PARRAY, ARR_CNT) ; function located in another file
...

turn into this
main.gen.psm file:

...
LOAD sB,  03
LOAD sA, 08       ;
fn_spi_read_byte_array(sB, sA)
...

However I can call it like this:

call fn_spi_read_byte_array

But it works not correct

setup script fails on ubuntu 16.04/18.04

May I suggest adding this line to the README file?

To install on Linux run:
sudo python setup.py install
Then use opbasm to run the program.

For people like me, who are not regular python users, this kind of help is needed.
Thanks.

Single quotes inside comments causing trouble

The following code will not assemble correctly:

proc a() {
	load s0, 0 ;I'm the zero reg
}

The problem is caused by the single quote (') in the comment, removing it solves the problem.

I know that the single quote is a quoting character in m4, but this is a really annoying problem, especially since this sometimes does not cause an error but instead just eats up some random instructions, cause some really strange bugs ("It works when I remove the comment...") Maybe one can fix this with some m4 magic?

Generic template: Not working in Vivado

The generic rom template picoblaze_rom.vhdl is not usable in Vivado 2017.2 because Vivado does not like line arguments in read_hex:

Procedure argument of type 'line' is not supported

(This is probably also a problem in your vhdl-extras library)

I inlined read_hex, but this caused Vivado to infer two 1Kx36 memories instead of the sufficient 1Kx18 (for <1024 instruction). I'm not sure if this is a bug/limitation of your code, forcing Vivado to use a 1Kx18 BRAM uses a few more LUTs, so this might be a intended optimization by Vivado.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.