New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{.volatile.} is almost useless #3382

Closed
rasendubi opened this Issue Sep 27, 2015 · 5 comments

Comments

Projects
None yet
5 participants
@rasendubi

As an embedded and kernel developer I need pointers to a volatile memory to work with memory-mapped hardware registers. Nim has a {.volatile.} pragma but it's a property of a variable.

let reg {.volatile.} = cast[ptr char](0x101f1000)

gives the following C output:

NIM_CHAR* volatile reg;
nimfr("kmain", "kernel.nim");
nimln(5, "kernel.nim");
reg = ((NIM_CHAR*) 270471168);

As you see, reg is a volatile pointer to a non-volatile memory. The behavior I want to achieve is a non-volatile pointer to a volatile memory:

NIM_CHAR volatile *reg;

I don't see a way to create such a variable in Nim. I would say, that's pretty critical: embedded and kernel-level programming is impossible without that.

As a fix I think of making volatile a property of a type rather than a variable. I expect to write the following:

let reg = cast[ptr[char {.volatile.}]](0x101f1000)
# or even
const reg = cast[ptr[char {.volatile.}]](0x101f1000)
# const reg {.volatile.} = ... doesn't even work now
@yglukhov

This comment has been minimized.

Show comment
Hide comment
@yglukhov

yglukhov Sep 28, 2015

Member

As a quick and dirty workaround you can use emit.

{.emit: "NIM_CHAR volatile* myPtr;".}
var myPtr {.nodecl, importc.}: ptr char
myPtr[] = 'A'

I guess this could be wrapped in a macro.

Member

yglukhov commented Sep 28, 2015

As a quick and dirty workaround you can use emit.

{.emit: "NIM_CHAR volatile* myPtr;".}
var myPtr {.nodecl, importc.}: ptr char
myPtr[] = 'A'

I guess this could be wrapped in a macro.

@rasendubi

This comment has been minimized.

Show comment
Hide comment
@rasendubi

rasendubi Sep 28, 2015

The other solution (from Rust: rust-lang/rust#11172) is to implement volatile_load and volatile_store functions.

The other solution (from Rust: rust-lang/rust#11172) is to implement volatile_load and volatile_store functions.

@Araq

This comment has been minimized.

Show comment
Hide comment
@Araq

Araq Sep 28, 2015

Member

Volatile is not a property of a type and should not be.

Member

Araq commented Sep 28, 2015

Volatile is not a property of a type and should not be.

@Araq

This comment has been minimized.

Show comment
Hide comment
@Araq

Araq Sep 29, 2015

Member

volatile_load and volatile_store is the superior solution indeed.

Member

Araq commented Sep 29, 2015

volatile_load and volatile_store is the superior solution indeed.

@dom96 dom96 added the Feature label Jan 16, 2016

Jeff-Ciesielski added a commit to Jeff-Ciesielski/Nim that referenced this issue Jan 23, 2017

Add volatile load/store
Adds volatile load/store capability to the impure part of the standard
library.  This makes use of two new C macros stored in the nimbase.h
file and some macro trickery to perform type checking on the nim side.
Note that this currently only supports numerical types.

Should resolve nim-lang#3382

Jeff-Ciesielski added a commit to Jeff-Ciesielski/Nim that referenced this issue Jan 23, 2017

Add volatile load/store
Adds volatile load/store capability to the impure part of the standard
library.  This makes use of two new C macros stored in the nimbase.h
file and some macro trickery to perform type checking on the nim side.
Note that this currently only supports numerical types.

Should resolve nim-lang#3382
@jcosborn

This comment has been minimized.

Show comment
Hide comment
@jcosborn

jcosborn Jan 23, 2017

Contributor

This seems to work. It involves an extra copy, but doesn't require any emits.

template volatileLoad*[T](p: ptr T): T =
  let x {.volatile.} = p[]
  x

template volatileStore*[T](p: ptr T, v: T) =
  let x {.volatile.} = v
  p[] = x

type VolatilePtr*[T] = distinct ptr T

template `[]`*[T](p: VolatilePtr[T]): T =
  volatileLoad((ptr T)(p))

template `[]=`*[T](p: VolatilePtr[T], v: T) =
  volatileStore((ptr T)(p), v)

when isMainModule:
  proc test =
    var t = 0
    var c = 0

    for i in 1..1000:
      volatileStore(addr t, 1)
      if volatileLoad(addr t)==1:
        inc c

    let p = VolatilePtr(addr t)

    for i in 1..1000:
      p[] = 2
      if p[]==2:
        inc c

    echo c

  test()
Contributor

jcosborn commented Jan 23, 2017

This seems to work. It involves an extra copy, but doesn't require any emits.

template volatileLoad*[T](p: ptr T): T =
  let x {.volatile.} = p[]
  x

template volatileStore*[T](p: ptr T, v: T) =
  let x {.volatile.} = v
  p[] = x

type VolatilePtr*[T] = distinct ptr T

template `[]`*[T](p: VolatilePtr[T]): T =
  volatileLoad((ptr T)(p))

template `[]=`*[T](p: VolatilePtr[T], v: T) =
  volatileStore((ptr T)(p), v)

when isMainModule:
  proc test =
    var t = 0
    var c = 0

    for i in 1..1000:
      volatileStore(addr t, 1)
      if volatileLoad(addr t)==1:
        inc c

    let p = VolatilePtr(addr t)

    for i in 1..1000:
      p[] = 2
      if p[]==2:
        inc c

    echo c

  test()

Jeff-Ciesielski added a commit to Jeff-Ciesielski/Nim that referenced this issue Jan 25, 2017

Add volatile load/store
Adds volatile load/store capability to the impure part of the standard
library.  Note that this currently only supports numerical types.

Should resolve nim-lang#3382

Jeff-Ciesielski added a commit to Jeff-Ciesielski/Nim that referenced this issue Jan 25, 2017

Add volatile load/store
Adds volatile load/store capability to the impure part of the standard
library.  Note that this currently only supports numerical types.

Should resolve nim-lang#3382

Jeff-Ciesielski added a commit to Jeff-Ciesielski/Nim that referenced this issue Jan 25, 2017

Add volatile load/store
Adds volatile load/store capability to the impure part of the standard
library.  Note that this currently only supports numerical types.

Should resolve nim-lang#3382

@Araq Araq closed this in #5263 Jan 25, 2017

Araq added a commit that referenced this issue Jan 25, 2017

Add volatile load/store (#5263)
Adds volatile load/store capability to the impure part of the standard
library.  Note that this currently only supports numerical types.

Should resolve #3382
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment